package kr.co.compcarecompany.Util;

import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Handler;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.Patterns;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttMessage;

import java.io.File;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import info.mqtt.android.service.Ack;
import info.mqtt.android.service.MqttAndroidClient;
import kr.co.compcarecompany.Activity.FragmentActivity;
import kr.co.compcarecompany.R;

public class Common {
    String TAG = "Common";
    String BASE_URL = "https://www.compcare.co.kr/";
    private static Common ourInstance;

    public static Common getInstance() {
        if (ourInstance == null) {
            ourInstance = new Common();
        }
        return ourInstance;
    }

    // 값 넣기(String)
    public void setPref(Context context, String key, String value) {
        SharedPreferences pref = context.getSharedPreferences(TAG, Activity.MODE_PRIVATE);
        SharedPreferences.Editor editor = pref.edit();
        editor.putString(key, value);
        editor.apply();
    }

    // 값 불러오기(string)
    public String getPref(Context context, String key) {
        Log.d("여기용@@@", "ㅇㅇㅇ");
        SharedPreferences pref = context.getSharedPreferences(TAG, Activity.MODE_PRIVATE);
        if (pref.contains(key)) {
            return pref.getString(key, "");
        } else {
            return null;
        }
    }

    // 값 넣기(boolean)
    public void setPref(Context context, String key, boolean value) {
        SharedPreferences pref = context.getSharedPreferences(TAG, Activity.MODE_PRIVATE);
        SharedPreferences.Editor editor = pref.edit();
        editor.putBoolean(key, value);
        editor.apply();
    }

    // 값 불러오기(boolean)
    public boolean getPref(Context context, String key, boolean value) {
        SharedPreferences pref = context.getSharedPreferences(TAG, Activity.MODE_PRIVATE);
        if (pref.contains(key)) {
            Log.d("getPref(" + key + ")", "true");
            return true;
        } else {
            Log.d("getPref(" + key + ")", "false");
            return false;
        }
    }

    // 값(Key Data) 삭제하기
    public void delPref(Context context, String key) {
        SharedPreferences pref = context.getSharedPreferences(TAG, Activity.MODE_PRIVATE);
        SharedPreferences.Editor editor = pref.edit();
        editor.remove(key);
        editor.apply();
    }

    // 값(ALL Data) 삭제하기
    public void delAllPref(Context context) {
        SharedPreferences pref = context.getSharedPreferences(TAG, Activity.MODE_PRIVATE);
        SharedPreferences.Editor editor = pref.edit();
        editor.clear();
        editor.apply();
    }

    public Object isNull(Object s) {
        if (s == null) {
            return "";
        }
        return s;
    }

    public String isNullToZero(String s) {
        if (s == null) {
            return "0";
        }
        return s;
    }

    public String isNullToZeroFloat(String s) {
        if (s == null) {
            return "0.0";
        } else if (s.equals("0")) {
            return "0.0";
        } else if (!s.contains(".")) {
            return s + ".0";
        }
        return s;
    }

    public int getWidth(Activity activity) {
        DisplayMetrics dm = activity.getApplicationContext().getResources().getDisplayMetrics();
        return dm.widthPixels;
    }

    public int getHeight(Activity activity) {
        DisplayMetrics dm = activity.getApplicationContext().getResources().getDisplayMetrics();
        return dm.heightPixels;
    }

    public int getDip(Context context, int dimen) {
        return (int) context.getResources().getDimension(dimen);
    }

    public String getBaseUrl(String mbid) {
        String baseUrl = BASE_URL;
        if (!TextUtils.isEmpty(mbid)) {
            baseUrl = String.format("https://%s.compcare.co.kr/", mbid);
        }

        return baseUrl;
    }

    public boolean isValidEmail(String email) {
        if (TextUtils.isEmpty(email)) {
            return false;
        } else {
            return Patterns.EMAIL_ADDRESS.matcher(email).matches();
        }
    }

    public void deleteDirectory(String dirPath) {
        File file = new File(dirPath);
        File[] childFileList = file.listFiles();
        if (childFileList != null) {
            for (File childFile : childFileList) {
                if (childFile.isDirectory()) {
                    deleteDirectory(childFile.getAbsolutePath());
                } else {
                    childFile.delete();
                }
            }

            file.delete();
        }
    }

    public String moneyFormatToWon(int inputMoney) {
        DecimalFormat decimalFormat = new DecimalFormat("#,##0");
        return decimalFormat.format(inputMoney);
    }

    public boolean isEllipsis(TextView textView) {
        // 1이 나온다는 것은 글씨가 줄여졌다는 것이다.
        if (textView.getLayout() != null) {
            return textView.getLayout().getEllipsisCount(textView.getLineCount() - 1) > 0;
        }
        return false;
    }

    public String isNullText(String str) {
        if (str == null) {
            return "";
        }
        return str;
    }

    public boolean isTextEmpty(Context context, TextView tv, String name) {
        if (tv.getText().toString().equals("")) {
            Toast.makeText(context, name + "을(를) 입력해 주세요.", Toast.LENGTH_LONG).show();
            return true;
        }
        return false;
    }

    public String convert_mqtt_value_string(String name, String value) {
        String con = "";
        if (value != null && !value.equals("")) {
            con = "'" + name + "':" + value;
        }
        return con;
    }

    public String convert_mqtt_value_int(String name, Integer value) {
        String con = "";
        if (value != null && value > 0) {
            con = "'" + name + "': " + value;
        } else {
            con = "'" + name + "': -1";
        }
        return con;
    }

    public String convert_max(String name, String value) {
        String con = "";
        if (value != null && !value.equals("")) {
            con = "'" + name + "':'>" + name + "," + value + "'";
        }
        return con;
    }


    public String valueConvert(String value) { // 월간 소비전력 용
        String ori_value = value;
        if (ori_value != null && ori_value.contains(".")) {
            ori_value = ori_value.substring(0, ori_value.indexOf("."));
        } else if (ori_value == null) {
            ori_value = "0";
        }
        return ori_value;
    }

    public String valueConvert1(String value) {
        String ori_value = value;
        if (ori_value != null && ori_value.contains(".")) {
            ori_value = ori_value.substring(0, ori_value.indexOf(".") + 2);
        } else if (ori_value == null) {
            ori_value = "0.0";
        } else {
            ori_value = ori_value + ".0";
        }
        return ori_value;
    }

    public String valueConvert2(String value) {
        String ori_value = value;
        if (ori_value.contains(".")) {
            ori_value = ori_value.substring(0, ori_value.indexOf(".") + 3);
        } else {
            ori_value = ori_value + ".00";
        }
        return ori_value;
    }

    public boolean isNumber(String str) {

        boolean check = true;
        for (int i = 0; i < str.length(); i++) {
            if (!Character.isDigit(str.charAt(i))) {
                check = false;
                break;
            }
        }
        return check;
    }

    public void condition_status(ImageView imageView, String data, String max_data, String up, String down) {

        float value = Float.parseFloat(data);
        float max_value = Float.parseFloat(max_data);
        float up_value = Float.parseFloat(up);
        float down_value = Float.parseFloat(down);

        if (value == 0) {
            imageView.setImageResource(R.color.color_chart_purple);

            //한계치 over >> 경고
        } else if (value > max_value || value < 0) {
            imageView.setImageResource(R.drawable.icon_red_square);

            //주의
        } else if (value > up_value || value < down_value) {
            imageView.setImageResource(R.drawable.icon_yellow_square);

            //정상
        } else {
            imageView.setImageResource(R.drawable.icon_green_square);
        }
    }

    public void condition_status_iot(Button button, String data, String max_data, String up, String down) {

        float value = Float.parseFloat(data);
        float max_value = Float.parseFloat(max_data);
        float up_value = Float.parseFloat(up);
        float down_value = Float.parseFloat(down);

        //한계치 over >> 경고
        if (value > max_value || value < 0) {
            button.setBackgroundResource(R.drawable.bg_red_round_opa40);

            //주의
        } else if (value > up_value || value < down_value) {
            button.setBackgroundResource(R.drawable.bg_yellow_round_opa40);

            //정상
        } else {
            button.setBackgroundResource(R.drawable.bg_green_round_opa40);
        }
    }

    public void toastShow(Context context, String message) {
        try {
            Toast toast = Toast.makeText(context, message, Toast.LENGTH_SHORT);
            toast.show();

            Handler toast_hdr = new Handler();
            toast_hdr.postDelayed(new Runnable() {
                @Override
                public void run() {
                    toast.cancel();
                }
            }, 1000);
        } catch (Exception ignored) {
        }
    }

    public void customToastShow_short(Context context, String message, FragmentActivity activity) {
        LayoutInflater inflater = activity.getLayoutInflater();
        View layout = inflater.inflate(R.layout.custom_toast_info, (ViewGroup) activity.findViewById(R.id.toastLL));
        TextView textView = layout.findViewById(R.id.toastTV);
        textView.setText(message);

        Toast toast = Toast.makeText(context, message, Toast.LENGTH_SHORT);
        toast.setGravity(Gravity.CENTER, 0, 0);
        toast.setView(layout);
        toast.show();
    }

    public void customToastShow_long(Context context, String message, FragmentActivity activity) {
        LayoutInflater inflater = activity.getLayoutInflater();
        View layout = inflater.inflate(R.layout.custom_toast_info, (ViewGroup) activity.findViewById(R.id.toastLL));
        TextView textView = layout.findViewById(R.id.toastTV);
        textView.setText(message);

        Toast toast = Toast.makeText(context, message, Toast.LENGTH_LONG);
        toast.setGravity(Gravity.CENTER, 0, 0);
        toast.setView(layout);
        toast.show();
    }

    public MqttAndroidClient mqtt_connect(Context context, MqttAndroidClient mqttAndroidClient) {

        String password = "comp1care@#";
        MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
        mqttConnectOptions.setUserName("compcare");
        mqttConnectOptions.setPassword(password.toCharArray());
        mqttConnectOptions.setConnectionTimeout(5);
        mqttConnectOptions.setCleanSession(true);

        String id = MqttClient.generateClientId();
        /* Create an MqttAndroidClient object and set a callback interface. */
        mqttAndroidClient = new MqttAndroidClient(context, "tcp://116.125.120.109:1883", id, Ack.MANUAL_ACK, null, false, 1000);
        /* Establish an MQTT connection */
        mqttAndroidClient.connect(mqttConnectOptions, null, new IMqttActionListener() {
            @Override
            public void onSuccess(IMqttToken asyncActionToken) {
                Log.d("연결했다@@@@", id);
            }

            @Override
            public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                Log.d("실패했다@@@@", id);
            }
        });
//        mqttAndroidClient.registerResources();
        return mqttAndroidClient;

    }

    public MqttAndroidClient mqtt_disconnect(MqttAndroidClient mqttAndroidClient) {
        mqttAndroidClient.unregisterResources();
        mqttAndroidClient.close();
        mqttAndroidClient.disconnect();
        return null;
    }

    public void unSubscribeTopic(String topic, MqttAndroidClient mqttAndroidClient) {

        IMqttToken unsubToken = mqttAndroidClient.unsubscribe(topic);
        unsubToken.setActionCallback(new IMqttActionListener() {
            @Override
            public void onSuccess(IMqttToken asyncActionToken) {
                Log.i("@@@", "unsubscribed succeed");
                // The subscription could successfully be removed from the client
            }

            @Override
            public void onFailure(IMqttToken asyncActionToken,
                                  Throwable exception) {
                Log.i("@@@", "unsubscribed failed");
            }
        });

    }

    public void subscribeTopic(String topic, MqttAndroidClient mqttAndroidClient) {

        IMqttToken subToken = mqttAndroidClient.subscribe(topic, 0);
        subToken.setActionCallback(new IMqttActionListener() {
            @Override
            public void onSuccess(IMqttToken asyncActionToken) {

            }

            @Override
            public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                new Thread(() -> {
                    try {
                        Thread.sleep(1000);
                        subscribeTopic(topic, mqttAndroidClient);
                    } catch (Exception ignored) {
                    }
                }).start();
            }
        });
    }

    public void publishMessage(String topic, String payload, MqttAndroidClient mqttAndroidClient) {
        MqttMessage message = new MqttMessage();
        message.setPayload(payload.getBytes());
        message.setQos(0);
        message.setRetained(false);

        IMqttToken pubToken = mqttAndroidClient.publish(topic, message);
        pubToken.setActionCallback(new IMqttActionListener() {
            @Override
            public void onSuccess(IMqttToken asyncActionToken) {

            }

            @Override
            public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                new Thread(() -> {
                    try {
                        Thread.sleep(1000);
                        publishMessage(topic, payload, mqttAndroidClient);
                    } catch (Exception ignored) {
                    }
                }).start();
            }
        });
    }

    public String[] encrypt(String password) throws NoSuchAlgorithmException {

        String new_salt = generateSalt();

        MessageDigest md = MessageDigest.getInstance("SHA-256");
        md.update(password.getBytes());
        md.update(new_salt.getBytes());

        return new String[]{String.format("%064x", new BigInteger(1, md.digest())), new_salt};
    }

    public static String generateSalt() throws NoSuchAlgorithmException {

        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");

        byte[] salt = new byte[16];
        random.nextBytes(salt);

        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < salt.length; i++) {
            sb.append(String.format("%02x", salt[i]));
        }

        return sb.toString();
    }

    public static boolean validationPassword(String pw) {
        Pattern p = Pattern.compile("^(?=.*[a-z])(?=.*\\d)(?=.*[$@$!%*?&])[A-Za-z\\d$@$!%*?&]{8,}");
        Matcher m = p.matcher(pw);

        if (m.matches()) {
            return true;
        }
        return false;
    }

    public long getTimeForAlarm(String type) throws ParseException {

        Calendar calendar = Calendar.getInstance();

        if (type.equals("month")) {
            calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) + 1);
            calendar.set(Calendar.DATE, 1);

        } else {
            calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH));
            calendar.set(Calendar.WEEK_OF_MONTH, calendar.get(Calendar.WEEK_OF_MONTH) + 1);
            calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);

        }

        SimpleDateFormat dataFormat = new SimpleDateFormat("yyyyMMdd090000", Locale.KOREA);
        String new_time = dataFormat.format(calendar.getTime());
        SimpleDateFormat new_dataFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.KOREA);
        Date date = new_dataFormat.parse(new_time);

        return date.getTime();

    }

    public String getDateOfMonth(int year, int month, String type) throws ParseException {

        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat dataFormat;
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month - 1);

        int day;
        if (type.equals("first")) {
            calendar.set(Calendar.DATE, 1);
            dataFormat = new SimpleDateFormat("yyyyMMdd000000", Locale.KOREA);

        } else {
            day = calendar.getActualMaximum(Calendar.DATE);
            calendar.set(Calendar.DATE, day);
            dataFormat = new SimpleDateFormat("yyyyMMdd235959", Locale.KOREA);

        }
        Log.d("month type@@@@", dataFormat.format(calendar.getTime()));
        String new_time = dataFormat.format(calendar.getTime());

        SimpleDateFormat new_dataFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.KOREA);
        Date date = new_dataFormat.parse(new_time);

        return date.getTime() + "000000";
    }

    public String getDateOfMonth2(int year, int month, String type) throws ParseException {

        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month - 1);

        SimpleDateFormat dataFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.KOREA);

        int day;
        if (type.equals("first")) {
            calendar.set(Calendar.DATE, 1);

        } else {
            day = calendar.getActualMaximum(Calendar.DATE);
            calendar.set(Calendar.DATE, day);
        }

        return dataFormat.format(calendar.getTime());
    }

    public int getOrderOfWeek(int year, int month) {

        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month - 1);
        calendar.set(Calendar.DATE, 0);

        return calendar.get(Calendar.DAY_OF_WEEK);
    }

    public int getWeekOfMonth(int year, int month) {

        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month - 1);
        calendar.set(Calendar.DATE, calendar.getActualMaximum(Calendar.DATE));
        return calendar.get(Calendar.WEEK_OF_MONTH);
    }

    public String getDateOfWeek(int year, int month, int week, String type, boolean today) throws ParseException {

        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month - 1);
        calendar.set(Calendar.WEEK_OF_MONTH, week);

        SimpleDateFormat dataFormat;

        if (type.equals("first")) {
            calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
            dataFormat = new SimpleDateFormat("yyyyMMdd000000", Locale.KOREA);

        } else {
            if (today) {
                calendar.set(Calendar.DATE, calendar.get(Calendar.DATE));
            } else {
                calendar.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
            }
            dataFormat = new SimpleDateFormat("yyyyMMdd235959", Locale.KOREA);
        }

        Log.d("week type@@@@", dataFormat.format(calendar.getTime()));

        String new_time = dataFormat.format(calendar.getTime());
        SimpleDateFormat new_dataFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.KOREA);
        Date date = new_dataFormat.parse(new_time);

        return date.getTime() + "000000";
    }

    public String getDateOfWeek2(int year, int month, int week, String type) throws ParseException {

        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month - 1);
        calendar.set(Calendar.WEEK_OF_MONTH, week);

        SimpleDateFormat dataFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.KOREA);

        if (type.equals("first")) {
            calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
        } else {
            calendar.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
        }

        return dataFormat.format(calendar.getTime());
    }


    public String convert_time(String ori_date, boolean is_start) throws ParseException {

        if (is_start) {
            ori_date = ori_date + ".000000";
        } else {
            ori_date = ori_date + ".235959";
        }

        SimpleDateFormat new_dataFormat = new SimpleDateFormat("yyyy.MM.dd.HHmmss", Locale.KOREA);
        Date date = new_dataFormat.parse(ori_date);

        return date.getTime() + "000000";
    }

    public String convert_time2(String ori_date, boolean is_start) throws ParseException {

        if (is_start) {
            ori_date = ori_date + "0000";
        } else {
            ori_date = ori_date + "5959";
        }

        SimpleDateFormat new_dataFormat = new SimpleDateFormat("yyyy.MM.dd.HHmmss", Locale.KOREA);
        Date date = new_dataFormat.parse(ori_date);

        return date.getTime() + "000000";
    }

    public int get_horsepower_output(String mc_horsepower) {
        int output = 0;

        switch (mc_horsepower) {
            case "20HP":
                output = 15;
                break;
            case "30HP":
                output = 22;
                break;
            case "50HP":
                output = 37;
                break;
            case "75HP":
                output = 55;
                break;
            case "100HP":
                output = 75;
                break;
            case "150HP":
                output = 110;
                break;
            case "200HP":
                output = 160;
                break;
        }

        return output;
    }

    public String fill_zero(int num) {
        if (num < 10) {
            return "0" + num;
        } else return num + "";
    }

    public int get_px(Activity activity, int dp) {
        DisplayMetrics out_metrics = new DisplayMetrics();
        activity.getWindowManager().getDefaultDisplay().getMetrics(out_metrics);
        return dp * out_metrics.densityDpi / 16;
    }
}
