package kr.co.icontrols.iotplatform.DataClass;

import android.app.Activity;

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

import java.io.IOException;
import java.util.ArrayList;

import kr.co.icontrols.iotplatform.Database.DBUtil;
import kr.co.icontrols.iotplatform.R;
import kr.co.icontrols.iotplatform.utils.HttpApi;
import okhttp3.Call;
import okhttp3.Response;

import static kr.co.icontrols.iotplatform.Database.DatabaseHelper.TABLE_DEVICE_RANK;
import static kr.co.icontrols.iotplatform.utils.CommonUtils.DismissConnectDialog;
import static kr.co.icontrols.iotplatform.utils.CommonUtils.ErrorLogOutput;
import static kr.co.icontrols.iotplatform.utils.CommonUtils.WarnLogOutput;
import static kr.co.icontrols.iotplatform.utils.CommonUtils.displayProgress;
import static kr.co.icontrols.iotplatform.utils.CommonUtils.restartApp;
import static kr.co.icontrols.iotplatform.utils.CommonUtils.showNotiMsg;
import static kr.co.icontrols.iotplatform.utils.Constants.DEFAULT_RANK;
import static kr.co.icontrols.iotplatform.utils.HttpApi.HTTP_OK;
import static kr.co.icontrols.iotplatform.utils.HttpApi.HTTP_UNAUTHORIZED;

public class UserInfo {

    private static String TAG = "UserInfo";

    public static String uid;
    public static String email;
    public static String phoneNumber;
    public static String nickname;
    public static String profile;
    public static boolean confirmed;
    public static boolean pushAccess;
    public static boolean autoUpdate;
    public static ArrayList<DeviceGroupInfo> dgroups = new ArrayList<>();
    public static ArrayList<DeviceInfo> devices = new ArrayList<>();
    public static ArrayList<LocationInfo> location = new ArrayList<>();
    public static ArrayList<String> dgroupsString = new ArrayList<>();
    public static int dgroupsCount;
    public static ArrayList<String> devicesString = new ArrayList<>();
    public static int deviceCount;
    public static ArrayList<WeatherInfo> weatherInfos = new ArrayList<>();
    public static boolean isSendPushToken = false;
    public static boolean isCheckInvite = false;

    private static long VALID_TIME = 500;//10 * 60 * 1000;
    public static long updateTimeUserInfo = -1;
    public static long updateTimeDevice = -1;
    public static long updateTimeGroup = -1;
    public static long updateTimeWeatherInfo = -1;

    public interface CallbackForUpdate {
        public void updateData();
    }

    public static void clear(){
        uid= "";
        email= "";
        phoneNumber= "";
        nickname= "";
        profile= "";
        confirmed= false;
        pushAccess= false;
        autoUpdate= false;
        dgroups.clear();
        devices.clear();
        location.clear();
        dgroupsString.clear();
        dgroupsCount= 0;
        devicesString.clear();
        deviceCount= 0;
    }

    public static void setUnSelectAllDevices() {
        for(int i = 0 ; i < devices.size() ; i++) {
            devices.get(i).isSelected = 0;
        }
    }

    public static void setUnSelectAllGroups() {
        for(int i = 0 ; i < dgroups.size() ; i++) {
            dgroups.get(i).isSelected = 0;
        }
    }

    public static void getUserInfo(Activity activity, CallbackForUpdate callback) {
        if(confirmed && ((System.currentTimeMillis() - updateTimeUserInfo) <= VALID_TIME)) {
            if(callback != null) {
                callback.updateData();
            }
        } else {
            displayProgress(activity, null, null);
            try {
                HttpApi.getUserInfo(new okhttp3.Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        e.printStackTrace();
                        ErrorLogOutput(TAG, "HttpApi.getUserInfo(onFailure) : " + e.toString());
                        DismissConnectDialog();
                        showNotiMsg(activity, activity.getString(R.string.snackbar_error_server));
                    }

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        if (response.code() == HTTP_OK) {
                            WarnLogOutput(TAG, "HttpApi.getUserInfo(onResponse) : HTTP_OK");
                            updateTimeUserInfo = System.currentTimeMillis();
                            try {
                                JSONObject json_data = new JSONObject(response.body().string());

                                uid = json_data.isNull("uid") ? "" : json_data.getString("uid");
                                email = json_data.isNull("email") ? "" : json_data.getString("email");
                                phoneNumber = json_data.isNull("phoneNumber") ? "" : json_data.getString("phoneNumber");
                                nickname = json_data.isNull("nickname") ? "" : json_data.getString("nickname");
                                profile = json_data.isNull("profile") ? "" : json_data.getString("profile");
                                confirmed = json_data.isNull("confirmed") ? false : json_data.getBoolean("confirmed");
                                pushAccess = json_data.isNull("pushAccess") ? false : json_data.getBoolean("pushAccess");
                                autoUpdate = json_data.isNull("autoUpdate") ? false : json_data.getBoolean("autoUpdate");

                                if (!json_data.isNull("locations")) {
                                    location.clear();
                                    JSONArray jarrayLocationInfo = new JSONArray(json_data.getString("locations"));
                                    for (int i = 0; i < jarrayLocationInfo.length(); i++) {
                                        JSONObject jObjectLocationInfo = jarrayLocationInfo.getJSONObject(i);
                                        LocationInfo locationInfo = new LocationInfo();

                                        locationInfo.locationId = jObjectLocationInfo.isNull("locationId") ? "" : jObjectLocationInfo.getString("locationId");
                                        locationInfo.latitude = jObjectLocationInfo.isNull("latitude") ? 0 : jObjectLocationInfo.getDouble("latitude");
                                        locationInfo.longitude = jObjectLocationInfo.isNull("longitude") ? 0 : jObjectLocationInfo.getDouble("longitude");

                                        if (!jObjectLocationInfo.isNull("address")) {
                                            JSONObject jObjectAddressInfo = new JSONObject(jObjectLocationInfo.getString("address"));

                                            locationInfo.address.city = jObjectAddressInfo.isNull("city") ? "" : jObjectAddressInfo.getString("city");
                                            locationInfo.address.district = jObjectAddressInfo.isNull("district") ? "" : jObjectAddressInfo.getString("district");
                                            locationInfo.address.town = jObjectAddressInfo.isNull("town") ? "" : jObjectAddressInfo.getString("town");
                                        }
                                        location.add(locationInfo);
                                    }
                                }

                                if (!json_data.isNull("dgroups")) {
                                    dgroupsString.clear();
                                    JSONObject jObjectDgroupInfo = new JSONObject(json_data.getString("dgroups"));
                                    if (!jObjectDgroupInfo.isNull("results")) {
                                        JSONArray arrJson = jObjectDgroupInfo.getJSONArray("results");
                                        for (int i = 0; i < arrJson.length(); i++) {
                                            dgroupsString.add(arrJson.getString(i));
                                        }
                                    }
                                    dgroupsCount = jObjectDgroupInfo.isNull("count") ? 0 : jObjectDgroupInfo.getInt("count");
                                }

                                if (!json_data.isNull("devices")) {
                                    devicesString.clear();
                                    JSONObject jObjectDeviceInfo = new JSONObject(json_data.getString("devices"));
                                    if (!jObjectDeviceInfo.isNull("results")) {
                                        JSONArray arrJson = jObjectDeviceInfo.getJSONArray("results");
                                        for (int i = 0; i < arrJson.length(); i++) {
                                            devicesString.add(arrJson.getString(i));
                                        }
                                    }
                                    deviceCount = jObjectDeviceInfo.isNull("count") ? 0 : jObjectDeviceInfo.getInt("count");
                                }
                                if(callback != null) {
                                    callback.updateData();
                                }
                                DismissConnectDialog();
                            } catch (JSONException e) {
                                e.printStackTrace();
                                ErrorLogOutput(TAG, "HttpApi.getUserInfo(JSONException)\n" + e.toString());
                                DismissConnectDialog();
                                showNotiMsg(activity, activity.getString(R.string.snackbar_error_server));
                            }
                        } else if(response.code() == HTTP_UNAUTHORIZED) {
                            showNotiMsg(activity, activity.getString(R.string.snackbar_expired_token));
                            restartApp(activity);
                        } else {
                            ErrorLogOutput(TAG, "HttpApi.getUserInfo(onResponse) Error code : " + response.code() + "\nresponse : " + response.toString());
                            showNotiMsg(activity, activity.getString(R.string.snackbar_error_server));
                            DismissConnectDialog();
                            try {
                                JSONObject json_data = new JSONObject(response.body().string());
                                ErrorLogOutput(TAG, "HttpApi.getUserInfo(onResponse) body : " + json_data.toString());
                            } catch (JSONException e) {
                                e.printStackTrace();
                                ErrorLogOutput(TAG, "HttpApi.getUserInfo(onResponse) JSONException : " + e.toString());
                            }
                        }
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
                ErrorLogOutput(TAG, "HttpApi.getUserInfo(Exception) : " + e.toString());
                showNotiMsg(activity, activity.getString(R.string.snackbar_error_server));
                DismissConnectDialog();
            }
        }
    }

    public static void getWeatherInfo(Activity activity, String locationId, CallbackForUpdate callback) {
        if(weatherInfos.size() > 0 && ((System.currentTimeMillis() - updateTimeWeatherInfo) <= VALID_TIME)) {
            if(callback != null) {
                callback.updateData();
            }
        } else {
            displayProgress(activity, null, null);
            try {
                HttpApi.getWeatherInfo(locationId, new okhttp3.Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        e.printStackTrace();
                        ErrorLogOutput(TAG, "HttpApi.getWeatherInfo(onFailure) : " + e.toString());
                        showNotiMsg(activity, activity.getString(R.string.snackbar_error_server));

                        if (callback != null) {
                            callback.updateData();
                        }
                    }

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        if (response.code() == HTTP_OK) {
                            WarnLogOutput(TAG, "HttpApi.getWeatherInfo(onResponse) : HTTP_OK");
                            updateTimeWeatherInfo = System.currentTimeMillis();
                            weatherInfos.clear();
                            try {
                                JSONObject json_data = new JSONObject(response.body().string());

                                WeatherInfo weatherInfo = new WeatherInfo();

                                weatherInfo.o3Value = json_data.isNull("o3Value") ? "-1" : json_data.getString("o3Value");
                                weatherInfo.o3Grad = json_data.isNull("o3Grad") ? "-1" : json_data.getString("o3Grad");
                                weatherInfo.pm10Value = json_data.isNull("pm10Value") ? "-1" : json_data.getString("pm10Value");
                                weatherInfo.pm10Grade = json_data.isNull("pm10Grade") ? "-1" : json_data.getString("pm10Grade");
                                weatherInfo.pm25Value = json_data.isNull("pm25Value") ? "-1" : json_data.getString("pm25Value");
                                weatherInfo.pm25Grade = json_data.isNull("pm25Grade") ? "-1" : json_data.getString("pm25Grade");
                                weatherInfo.adDatetime = json_data.isNull("adDatetime") ? "-1" : json_data.getString("adDatetime");

                                weatherInfo.sky = json_data.isNull("sky") ? "-1" : json_data.getString("sky");
                                weatherInfo.pty = json_data.isNull("pty") ? "-1" : json_data.getString("pty");
                                weatherInfo.rn1 = json_data.isNull("rn1") ? "-1" : json_data.getString("rn1");
                                weatherInfo.reh = json_data.isNull("reh") ? "-999" : json_data.getString("reh");
                                weatherInfo.t1h = json_data.isNull("t1h") ? "-999" : json_data.getString("t1h");
                                weatherInfo.wdDatetime = json_data.isNull("wdDatetime") ? "" : json_data.getString("wdDatetime");

                                weatherInfos.add(weatherInfo);

                                if (callback != null) {
                                    callback.updateData();
                                }

                            } catch (JSONException e) {
                                e.printStackTrace();
                                ErrorLogOutput(TAG, "HttpApi.getWeatherInfo(JSONException)\n" + e.toString());
                                DismissConnectDialog();
                                showNotiMsg(activity, activity.getString(R.string.snackbar_error_server));

                                if (callback != null) {
                                    callback.updateData();
                                }
                            }
                        } else if(response.code() == HTTP_UNAUTHORIZED) {
                            showNotiMsg(activity, activity.getString(R.string.snackbar_expired_token));
                            restartApp(activity);
                        } else {
                            ErrorLogOutput(TAG, "HttpApi.getWeatherInfo(onResponse) Error code : " + response.code() + "\nresponse : " + response.toString());
                            showNotiMsg(activity, activity.getString(R.string.snackbar_error_server));
                            DismissConnectDialog();
                            try {
                                JSONObject json_data = new JSONObject(response.body().string());
                                ErrorLogOutput(TAG, "HttpApi.getWeatherInfo(onResponse) body : " + json_data.toString());
                            } catch (JSONException e) {
                                e.printStackTrace();
                                ErrorLogOutput(TAG, "HttpApi.getWeatherInfo(onResponse) JSONException : " + e.toString());
                            }


                            if (callback != null) {
                                callback.updateData();
                            }
                        }
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
                ErrorLogOutput(TAG, "HttpApi.getWeatherInfo(Exception) : " + e.toString());
                showNotiMsg(activity, activity.getString(R.string.snackbar_error_server));
                DismissConnectDialog();

                if (callback != null) {
                    callback.updateData();
                }
            }
        }
    }

    public static void getDevice(Activity activity, CallbackForUpdate callback) {
        if(devices.size() > 0 && ((System.currentTimeMillis() - updateTimeDevice) <= VALID_TIME)) {
            if(callback != null) {
                callback.updateData();
            }
        } else {
            devices.clear();
            displayProgress(activity, null,null);
            try{
                HttpApi.getAllDevice(new okhttp3.Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        e.printStackTrace();
                        ErrorLogOutput(TAG, "HttpApi.getAllDevice(onFailure)\n" + e.toString());
                        DismissConnectDialog();
                        showNotiMsg(activity,"스마트 조명 목록 조회에 실패하였습니다");
                        if(callback != null) {
                            callback.updateData();
                        }
                    }

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        if(response.code() == HTTP_OK) {
                            WarnLogOutput(TAG, "HttpApi.getAllDevice(onResponse) : HTTP_OK");
                            updateTimeDevice = System.currentTimeMillis();
                            try {
                                JSONObject json_data = new JSONObject(response.body().string());

                                UserInfo.deviceCount = json_data.isNull("count") ? 0 : json_data.getInt("count");

                                if(UserInfo.deviceCount > 0) {
                                    JSONArray jarrayAll = new JSONArray(json_data.getString("results"));
                                    for (int i = 0; i < jarrayAll.length(); i++) {
                                        JSONObject jObject = jarrayAll.getJSONObject(i);
                                        DeviceInfo item = new DeviceInfo(
                                                jObject.isNull("deviceId") ? "" : jObject.getString("deviceId"),
                                                jObject.isNull("deviceType") ? "" : jObject.getString("deviceType"),
                                                jObject.isNull("friendlyName") ? "" : jObject.getString("friendlyName"),
                                                jObject.isNull("sharedFriendlyName") ? "" : jObject.getString("sharedFriendlyName"),
                                                jObject.isNull("dgroupId") ? "" : jObject.getString("dgroupId"),
                                                jObject.isNull("dgroupName") ? "" : jObject.getString("dgroupName"),
                                                jObject.isNull("ownerId") ? "" : jObject.getString("ownerId"),
                                                DEFAULT_RANK,
                                                DEFAULT_RANK
                                        );

                                        DeviceInfo localDbItem = DBUtil.getDeviceInfoForId(TABLE_DEVICE_RANK, item.deviceId);
                                        if (localDbItem == null) {
                                            DBUtil.putDeviceInfo(TABLE_DEVICE_RANK, item);
                                        } else {
                                            item.rank = localDbItem.rank;
                                            item.groupRank = localDbItem.groupRank;
                                            DBUtil.updateDeviceItem(TABLE_DEVICE_RANK, item);
                                        }
                                    }

                                    ArrayList<DeviceInfo> deviceInfos = DBUtil.getAllDeviceInfos(TABLE_DEVICE_RANK);
                                    for (DeviceInfo d : deviceInfos) {
                                        devices.add(d);
                                    }
                                    deviceInfos.clear();
                                }

                                if(callback != null) {
                                    callback.updateData();
                                }
                                DismissConnectDialog();
                            } catch (JSONException e) {
                                e.printStackTrace();
                                ErrorLogOutput(TAG, "HttpApi.getAllDevice(JSONException)\n" + e.toString());
                                showNotiMsg(activity,"스마트 조명 목록 조회에 실패하였습니다");
                                DismissConnectDialog();
                                if(callback != null) {
                                    callback.updateData();
                                }
                            }
                        } else if(response.code() == HTTP_UNAUTHORIZED) {
                            showNotiMsg(activity, activity.getString(R.string.snackbar_expired_token));
                            restartApp(activity);
                        } else {
                            ErrorLogOutput(TAG, "HttpApi.getAllDevice(onResponse) Error code : " + response.code() + "\nresponse : " + response.toString());
                            showNotiMsg(activity,"스마트 조명 목록 조회에 실패하였습니다 : " + response.code());
                            DismissConnectDialog();
                            try {
                                JSONObject json_data = new JSONObject(response.body().string());
                                ErrorLogOutput(TAG, "HttpApi.getAllDevice(onResponse) body : " + json_data.toString());
                            } catch (JSONException e) {
                                ErrorLogOutput(TAG, "HttpApi.getAllDevice(onResponse) JSONException : " + e.toString());
                            }
                            if(callback != null) {
                                callback.updateData();
                            }
                        }
                    }
                });
            } catch(Exception e){
                e.printStackTrace();
                ErrorLogOutput(TAG, "HttpApi.getDeviceListInDeviceGroup(Exception)\n" + e.toString());
                showNotiMsg(activity,"스마트 조명 목록 조회에 실패하였습니다");
                DismissConnectDialog();
                if(callback != null) {
                    callback.updateData();
                }
            }
        }
    }

    public static void getGroup(Activity activity, CallbackForUpdate callback) {
        dgroups.clear();
        if(dgroups.size() > 0 && ((System.currentTimeMillis() - updateTimeGroup) <= VALID_TIME)) {
            if(callback != null) {
                callback.updateData();
            }
        } else {
            displayProgress(activity,"","");
            try {
                HttpApi.getDeviceGroupList(new okhttp3.Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        e.printStackTrace();
                        ErrorLogOutput(TAG, "HttpApi.getDeviceGroupList(onFailure)\n" + e.toString());
                        DismissConnectDialog();
                        if(callback != null) {
                            callback.updateData();
                        }
                    }

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        if(response.code() == HTTP_OK) {
                            updateTimeGroup = System.currentTimeMillis();
                            WarnLogOutput(TAG, "HttpApi.getDeviceGroupList(onResponse) : HTTP_OK");
                            try {
                                JSONObject json_data = new JSONObject(response.body().string());
                                JSONArray jarrayAll = new JSONArray(json_data.getString("results"));
                                for (int i = 0; i < jarrayAll.length(); i++) {
                                    JSONObject jObject = jarrayAll.getJSONObject(i);
                                    DeviceGroupInfo item = new DeviceGroupInfo(jObject.isNull("dgroupId") ? "" : jObject.getString("dgroupId"),
                                            jObject.isNull("friendlyName") ? "" : jObject.getString("friendlyName"),
                                            jObject.isNull("icon") ? "" : jObject.getString("icon"),
                                            jObject.isNull("index") ? 99 : jObject.getInt("index"));

                                    dgroups.add(item);
                                }
                                if(callback != null) {
                                    callback.updateData();
                                }
                                DismissConnectDialog();
                            } catch (JSONException e) {
                                e.printStackTrace();
                                ErrorLogOutput(TAG, "HttpApi.getDeviceGroupList(JSONException)\n" + e.toString());
                                DismissConnectDialog();
                                if(callback != null) {
                                    callback.updateData();
                                }
                            }
                        } else if(response.code() == HTTP_UNAUTHORIZED) {
                            showNotiMsg(activity, activity.getString(R.string.snackbar_expired_token));
                            restartApp(activity);
                        } else {
                            ErrorLogOutput(TAG, "HttpApi.getDeviceGroupList(onResponse) Error code : " + response.code() + "\nresponse : " + response.toString());
                            try {
                                JSONObject json_data = new JSONObject(response.body().string());
                                ErrorLogOutput(TAG, "HttpApi.getDeviceGroupList(onResponse) body : " + json_data.toString());
                            } catch (JSONException e) {
                                ErrorLogOutput(TAG, "HttpApi.getDeviceGroupList(onResponse) JSONException : " + e.toString());
                            }
                            DismissConnectDialog();
                            if(callback != null) {
                                callback.updateData();
                            }
                        }
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
                ErrorLogOutput(TAG, "HttpApi.getDeviceGroupList(Exception)\n" + e.toString());
                DismissConnectDialog();
                if(callback != null) {
                    callback.updateData();
                }
            }
        }
    }

}
