package uprrp.tania.networking;

import android.os.AsyncTask;
import android.util.Log;

import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;

import javax.net.ssl.HttpsURLConnection;

import uprrp.tania.utils.URLEventListener;
import uprrp.tania.models.EmptyUserStatusModel;
import uprrp.tania.models.UserStatusModel;

public class FetchUserStatus extends AsyncTask<String, Void, JSONArray> {

    private static final String TAG = "FetchUserStatus";
    private static final String userStatusBaseURL = "https://tania.uprrp.edu/status.php?tk=";
    private final URLEventListener myCallBack;

    public FetchUserStatus(URLEventListener callback) {
        this.myCallBack = callback;
    }

    @Override
    protected JSONArray doInBackground(String... deviceTokenArray) {
        String deviceToken = deviceTokenArray[0]; // array will only ever contain a single element

        try {

            URL url = new URL(userStatusBaseURL + deviceToken);
            Log.d(TAG, "token:" + deviceToken); // log
            Log.d(TAG, "url:" + url.toString()); // log
            HttpsURLConnection httpURLConnection = (HttpsURLConnection) url.openConnection();
            InputStream inputStream = httpURLConnection.getInputStream();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            StringBuilder serverResponse =  new StringBuilder();

            String line = "";
            while(line != null) {
                serverResponse.append(line);
                line = bufferedReader.readLine();
            }

            String response = serverResponse.toString();
            Log.d(TAG, "rawString:" + response); // log
            if(response.contains("No joda")) { // no esta inscrito
                return new JSONArray("[]");
            } else {
                return new JSONArray(response);
            }

        } catch (MalformedURLException e) {
            Log.e(TAG, "Wrong URL used!");
            e.printStackTrace();
            return null;
        } catch (IOException e) {
            Log.e(TAG, "IOStream error occurred!");
            e.printStackTrace();
            return null;
        } catch (JSONException e) {
            Log.e(TAG, "Couldn't construct return JSON!");
            e.printStackTrace();
            return null;
        }

    }

    @Override
    protected void onPostExecute(JSONArray arr) {
        super.onPostExecute(arr);

        if(this.myCallBack == null) {
            Log.e(TAG, "Callback wasn't initialized first!");
            return;
        }

        if(arr == null) {
            this.myCallBack.onFailure(new Exception("Something went wrong with FetchUserStatus.doInBackground()!"));
            return;
        }

        // If json array is empty, return empty user status
        if(arr.length() == 0) {
            Log.d(TAG, "SENT EMPTY USER STATUS");
            UserStatusModel userData = new EmptyUserStatusModel();
            this.myCallBack.onSuccess(userData);
            return;
        }

        // Decode into UserStatusModel and send
        try {

            // TODO: Should find moment that is nearest to current date,
            //  instead of assuming it will always be sorted (just in case)
            JSONObject obj = arr.getJSONObject(0);

            // Actual decoding
            Log.d(TAG, "rawString:" + obj.toString());
            GsonBuilder builder = new GsonBuilder();
            builder.setPrettyPrinting();
            UserStatusModel userStatus = builder.create().fromJson(obj.toString(), UserStatusModel.class);
            Log.d(TAG,"reconstructedJSON:\n" + builder.create().toJson(userStatus));
            this.myCallBack.onSuccess(userStatus);

        } catch(JsonSyntaxException e) {
            this.myCallBack.onFailure(new Exception("Something went wrong during Gson decoding step in FetchUserStatus.onPostExecute()!"));
        } catch (JSONException e) {
            this.myCallBack.onFailure(new Exception("Something went wrong during JSONObject extraction step in FetchUserStatus.onPostExecute()!"));
        }
    }

}
