package kr.co.icontrols.iotplatform.utils;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.os.Debug;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.amazonaws.mobileconnectors.cognitoidentityprovider.CognitoDevice;
import com.amazonaws.mobileconnectors.cognitoidentityprovider.CognitoUser;
import com.amazonaws.mobileconnectors.cognitoidentityprovider.CognitoUserSession;
import com.amazonaws.mobileconnectors.cognitoidentityprovider.continuations.AuthenticationContinuation;
import com.amazonaws.mobileconnectors.cognitoidentityprovider.continuations.ChallengeContinuation;
import com.amazonaws.mobileconnectors.cognitoidentityprovider.continuations.ChooseMfaContinuation;
import com.amazonaws.mobileconnectors.cognitoidentityprovider.continuations.MultiFactorAuthenticationContinuation;
import com.amazonaws.mobileconnectors.cognitoidentityprovider.continuations.NewPasswordContinuation;
import com.amazonaws.mobileconnectors.cognitoidentityprovider.handlers.AuthenticationHandler;
import com.google.android.material.snackbar.Snackbar;

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

import java.io.IOException;
import java.util.List;
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import kr.co.icontrols.iotplatform.BuildConfig;
import kr.co.icontrols.iotplatform.DataClass.UserInfo;
import kr.co.icontrols.iotplatform.IotPlatformApplication;
import kr.co.icontrols.iotplatform.LoginActivity;
import kr.co.icontrols.iotplatform.PopupActivity;
import kr.co.icontrols.iotplatform.ProfileUserActivity;
import kr.co.icontrols.iotplatform.R;
import kr.co.icontrols.iotplatform.SplashActivity;
import kr.co.icontrols.iotplatform.cognito.AppHelper;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;

import static android.app.Activity.RESULT_CANCELED;
import static android.app.Activity.RESULT_OK;
import static kr.co.icontrols.iotplatform.utils.Constants.GROUP_BACKGROUND_00_STRING;
import static kr.co.icontrols.iotplatform.utils.Constants.GROUP_BACKGROUND_01_STRING;
import static kr.co.icontrols.iotplatform.utils.Constants.GROUP_BACKGROUND_02_STRING;
import static kr.co.icontrols.iotplatform.utils.Constants.GROUP_BACKGROUND_03_STRING;
import static kr.co.icontrols.iotplatform.utils.Constants.GROUP_BACKGROUND_04_STRING;
import static kr.co.icontrols.iotplatform.utils.Constants.GROUP_BACKGROUND_05_STRING;
import static kr.co.icontrols.iotplatform.utils.Constants.GROUP_BACKGROUND_06_STRING;
import static kr.co.icontrols.iotplatform.utils.Constants.GROUP_BACKGROUND_07_STRING;
import static kr.co.icontrols.iotplatform.utils.Constants.GROUP_BACKGROUND_08_STRING;
import static kr.co.icontrols.iotplatform.utils.Constants.GROUP_BACKGROUND_09_STRING;
import static kr.co.icontrols.iotplatform.utils.Constants.GROUP_IMG_00_STRING;
import static kr.co.icontrols.iotplatform.utils.Constants.GROUP_IMG_01_STRING;
import static kr.co.icontrols.iotplatform.utils.Constants.GROUP_IMG_02_STRING;
import static kr.co.icontrols.iotplatform.utils.Constants.GROUP_IMG_03_STRING;
import static kr.co.icontrols.iotplatform.utils.Constants.GROUP_IMG_04_STRING;
import static kr.co.icontrols.iotplatform.utils.Constants.GROUP_IMG_05_STRING;
import static kr.co.icontrols.iotplatform.utils.Constants.GROUP_IMG_06_STRING;
import static kr.co.icontrols.iotplatform.utils.Constants.GROUP_IMG_07_STRING;
import static kr.co.icontrols.iotplatform.utils.Constants.GROUP_IMG_08_STRING;
import static kr.co.icontrols.iotplatform.utils.Constants.GROUP_IMG_09_STRING;
import static kr.co.icontrols.iotplatform.utils.Constants.RESULT_RESEND_CONFIRM;
import static kr.co.icontrols.iotplatform.utils.SharedPrefUtil.AUTO_LOGIN;
import static kr.co.icontrols.iotplatform.utils.SharedPrefUtil.BACKGROUND_WAIT_TIME;
import static kr.co.icontrols.iotplatform.utils.SharedPrefUtil.DEFAULT_AUTO_LOGIN;
import static kr.co.icontrols.iotplatform.utils.SharedPrefUtil.DEFAULT_BACKGROUND_WAIT_TIME;
import static kr.co.icontrols.iotplatform.utils.SharedPrefUtil.DEFAULT_LOGIN_TIME;
import static kr.co.icontrols.iotplatform.utils.SharedPrefUtil.LOGIN_TIME;
import static kr.co.icontrols.iotplatform.utils.SharedPrefUtil.getLong;
import static kr.co.icontrols.iotplatform.utils.SharedPrefUtil.putBoolean;
import static kr.co.icontrols.iotplatform.utils.SharedPrefUtil.putLong;

public class CommonUtils {

    private final static String TAG = "CommonUtils";

    // 로그 출력 옵션
    private final static boolean DEBUG_LOG_ON = BuildConfig.DEBUG?true:false;
    private final static boolean ERROR_LOG_ON = BuildConfig.DEBUG?true:false;
    private final static boolean WARN_LOG_ON = BuildConfig.DEBUG?true:false;
    private final static boolean INFO_LOG_ON = BuildConfig.DEBUG?true:false;

    public static void DebugLogOutput(String tag, String s) {
        if (DEBUG_LOG_ON) Log.d(tag, s);
    }

    public static void ErrorLogOutput(String tag, String s) {
        if (ERROR_LOG_ON) Log.e(tag, s);
    }

    public static void WarnLogOutput(String tag, String s) {
        if (WARN_LOG_ON) Log.w(tag, s);
    }

    public static void InfoLogOutput(String tag, String s) {
        if (INFO_LOG_ON) Log.i(tag, s);
    }

    public static final  int PERMISSION_ALL = 1;
    public static final  String[] PERMISSIONS = {
            android.Manifest.permission.CALL_PHONE,
            android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
            android.Manifest.permission.READ_EXTERNAL_STORAGE,
            android.Manifest.permission.CAMERA,
            Manifest.permission.ACCESS_FINE_LOCATION,
    };

    private static final int EXIT_TIME = 2000;
    private static boolean mIsCancelToExit;

    private static CustomProgressDialog mConnectProgressDialog;
    private final static int DEFUALT_HIDEN_PROGRESSBAR_DELAY_TIME = 5000;
    private static Timer mDialogTimer;
    private static long mShowProgressTime = 0;

    private static long BACKGROUND_WAIT_EXIT_TIME = 30*60*1000;

    /**
     * 로딩화면 시작 함수
     *
     * @param activity
     * @param str
     * @param str2
     */
    public static void displayProgress(final Activity activity, String str, String str2){
        displayProgress(activity, str, str2, DEFUALT_HIDEN_PROGRESSBAR_DELAY_TIME);
    }

    public static void displayProgress(final Activity activity, String str, String str2, long hideTime) {
        if(mConnectProgressDialog != null)
            return;
        mShowProgressTime = System.currentTimeMillis();
        mConnectProgressDialog = new CustomProgressDialog(activity, str, str2);
        mConnectProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
            @Override
            public void onCancel(DialogInterface dialog) {

            }
        });

        mConnectProgressDialog.setCancelable(false);
        if (mDialogTimer != null) {
            mDialogTimer.cancel();
            mDialogTimer.purge();
        }
        mDialogTimer = new Timer();
        mDialogTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                if (mConnectProgressDialog != null)
                    activity.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            if(mConnectProgressDialog != null) {
                                //mConnectProgressDialog.showTitle();
                                //mConnectProgressDialog.showSubTitle();
                                DismissConnectDialog();
                            }
                        }
                    });
            }
        }, hideTime);
        mConnectProgressDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {

            @Override
            public void onDismiss(DialogInterface dialog) {
                DismissConnectDialog();
            }
        });

        //mConnectProgressDialog.show();

        try {
            mConnectProgressDialog.show();
        } catch (Exception e) {
            e.printStackTrace();
            mConnectProgressDialog = null;
        }
    }

    /**
     * 로딩화면 종료 함수
     */
    public static void DismissConnectDialog() {
        long delay = System.currentTimeMillis()-500;
        if(mShowProgressTime > delay) {
            Timer delayHideProgressTimer = new Timer();
            delayHideProgressTimer.schedule(new TimerTask() {
                @Override
                public void run() {
                    DismissConnectDialog();
                }
            },mShowProgressTime - delay + 100);
            return;
        }

        if (mDialogTimer != null) {
            mDialogTimer.cancel();
            mDialogTimer.purge();
        }
        if (mConnectProgressDialog != null) {
            try {
                mConnectProgressDialog.dismiss();
            }
            catch (IllegalArgumentException e) {
                e.printStackTrace();
            }
            mConnectProgressDialog = null;
        }
    }
    public static void ForceDismissConnectDialog() {
        if (mDialogTimer != null) {
            mDialogTimer.cancel();
            mDialogTimer.purge();
        }
        if (mConnectProgressDialog != null) {
            try {
                mConnectProgressDialog.dismiss();
            }
            catch (IllegalArgumentException e) {
                e.printStackTrace();
            }
            mConnectProgressDialog = null;
        }
    }

    public static boolean IsRunningProgress(){
        return (mConnectProgressDialog != null);
    }

    public static CustomProgressDialog getProgressDialog() {
        return mConnectProgressDialog;
    }

    /**
     * 로딩화면 타이틀 문구 표시
     *
     * @param str
     */
    public static void progressDialogShowTitle(String str) {
        if (mConnectProgressDialog != null) {
            mConnectProgressDialog.showTitle(str);
        }
    }

    /**
     * 로딩화면 서버타이틀 문구 표시
     *
     * @param str
     */
    public static void progressDialogShowSubTitle(String str) {
        if (mConnectProgressDialog != null) {
            mConnectProgressDialog.showSubTitle(str);
        }
    }


    /**
     * 이메일 형식 유효성 체크 함수.
     * @param email
     * @return
     */
    public static boolean isEmailValid(String email) {
        String expression = "^[\\w\\.-]+@([\\w\\-]+\\.)+[\\w\\-]+$";
        Pattern pattern = Pattern.compile(expression, Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(email);
        return matcher.matches();
    }

    /**
     * 암호 설정을 위한 유효성 체크 함수
     * @param s
     * @return
     */
    public static boolean isPasswordValid(String s){
        /*
        if(s.matches("[0-9]+")){
            return false;
        } else if(s.matches("[^0-9]+")){
            return false;
        } else if(s.matches("[\\w-]+")){
            return  true;
        }
        return false;
         */

        return s.matches("^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*\\W)(?=.\\S+$).{8,20}$");
    }

    public static void cancelToExit(final Activity activity) {
        if(mIsCancelToExit){
            activity.finish();
            System.exit(0);
        } else {
            mIsCancelToExit = true;
            Toast.makeText(activity,activity.getString(R.string.cancel_exit_app),Toast.LENGTH_SHORT).show();
            Timer exitTimer = new Timer();
            exitTimer.schedule(new TimerTask() {
                @Override
                public void run() {
                    activity.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            try {

                            } catch (Exception e){
                                e.printStackTrace();
                            } finally {
                                mIsCancelToExit = false;
                            }
                        }
                    });
                }
            }, EXIT_TIME);
        }
    }

    //Hide Keypad
    public static void setupUI(final Activity activity, View view) {
        //Set up touch listener for non-text box views to hide keyboard.
        if(!(view instanceof EditText)) {
            view.setOnTouchListener(new View.OnTouchListener() {
                public boolean onTouch(View v, MotionEvent event) {
                    hideSoftKeyboard(activity);
                    return false;
                }
            });
        }

        //If a layout container, iterate over children and seed recursion.
        if (view instanceof ViewGroup) {

            for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {

                View innerView = ((ViewGroup) view).getChildAt(i);

                setupUI(activity, innerView);
            }
        }
    }

    /**
     * 소프트 키보드 숨김 함수
     * @param activity
     */
    public static void hideSoftKeyboard(Activity activity) {
        if(activity != null && activity.getCurrentFocus() != null && activity.getCurrentFocus().getWindowToken()!= null) {
            InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
            inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
        }
    }

    public static int getGroupImageResource(String s) {
        int rscID = R.drawable.img_group_01;
        switch (s) {
            case GROUP_IMG_00_STRING:
                rscID = R.drawable.img_group_01;
                break;
            case GROUP_IMG_01_STRING:
                rscID = R.drawable.img_group_01;
                break;
            case GROUP_IMG_02_STRING:
                rscID = R.drawable.img_group_02;
                break;
            case GROUP_IMG_03_STRING:
                rscID = R.drawable.img_group_03;
                break;
            case GROUP_IMG_04_STRING:
                rscID = R.drawable.img_group_04;
                break;
            case GROUP_IMG_05_STRING:
                rscID = R.drawable.img_group_05;
                break;
            case GROUP_IMG_06_STRING:
                rscID = R.drawable.img_group_06;
                break;
            case GROUP_IMG_07_STRING:
                rscID = R.drawable.img_group_07;
                break;
            case GROUP_IMG_08_STRING:
                rscID = R.drawable.img_group_08;
                break;
            case GROUP_IMG_09_STRING:
                rscID = R.drawable.img_group_09;
                break;
        }

        return rscID;
    }

    public static int getGroupImageIndex(String s) {
        int index = 1;
        switch (s) {
            case GROUP_IMG_00_STRING:
                index = 1;
                break;
            case GROUP_IMG_01_STRING:
                index = 1;
                break;
            case GROUP_IMG_02_STRING:
                index = 2;
                break;
            case GROUP_IMG_03_STRING:
                index = 3;
                break;
            case GROUP_IMG_04_STRING:
                index = 4;
                break;
            case GROUP_IMG_05_STRING:
                index = 5;
                break;
            case GROUP_IMG_06_STRING:
                index = 6;
                break;
            case GROUP_IMG_07_STRING:
                index = 7;
                break;
            case GROUP_IMG_08_STRING:
                index = 8;
                break;
            case GROUP_IMG_09_STRING:
                index = 9;
                break;
        }
        return index;
    }

    public static String getGroupImageString(int index) {
        String str = GROUP_IMG_00_STRING;
        switch (index) {
            case 0:
                str = GROUP_IMG_01_STRING;
                break;
            case 1:
                str = GROUP_IMG_01_STRING;
                break;
            case 2:
                str = GROUP_IMG_02_STRING;
                break;
            case 3:
                str = GROUP_IMG_03_STRING;
                break;
            case 4:
                str = GROUP_IMG_04_STRING;
                break;
            case 5:
                str = GROUP_IMG_05_STRING;
                break;
            case 6:
                str = GROUP_IMG_06_STRING;
                break;
            case 7:
                str = GROUP_IMG_07_STRING;
                break;
            case 8:
                str = GROUP_IMG_08_STRING;
                break;
            case 9:
                str = GROUP_IMG_09_STRING;
                break;
        }
        return str;
    }

    public static int getGroupBackgournResourceWithIcon(String s) {
        int rscID = R.drawable.bg_group_home_01;
        switch (s) {
            case GROUP_IMG_00_STRING:
                rscID = R.drawable.bg_group_home_01;
                break;
            case GROUP_IMG_01_STRING:
                rscID = R.drawable.bg_group_home_01;
                break;
            case GROUP_IMG_02_STRING:
                rscID = R.drawable.bg_group_home_02;
                break;
            case GROUP_IMG_03_STRING:
                rscID = R.drawable.bg_group_home_03;
                break;
            case GROUP_IMG_04_STRING:
                rscID = R.drawable.bg_group_home_04;
                break;
            case GROUP_IMG_05_STRING:
                rscID = R.drawable.bg_group_home_05;
                break;
            case GROUP_IMG_06_STRING:
                rscID = R.drawable.bg_group_home_06;
                break;
            case GROUP_IMG_07_STRING:
                rscID = R.drawable.bg_group_home_07;
                break;
            case GROUP_IMG_08_STRING:
                rscID = R.drawable.bg_group_home_08;
                break;
            case GROUP_IMG_09_STRING:
                rscID = R.drawable.bg_group_home_09;
                break;
        }

        return rscID;
    }

    public static String getGroupBackgroundString(int index) {
        String str = GROUP_BACKGROUND_00_STRING;
        switch (index) {
            case 0:
                str = GROUP_BACKGROUND_01_STRING;
                break;
            case 1:
                str = GROUP_BACKGROUND_01_STRING;
                break;
            case 2:
                str = GROUP_BACKGROUND_02_STRING;
                break;
            case 3:
                str = GROUP_BACKGROUND_03_STRING;
                break;
            case 4:
                str = GROUP_BACKGROUND_04_STRING;
                break;
            case 5:
                str = GROUP_BACKGROUND_05_STRING;
                break;
            case 6:
                str = GROUP_BACKGROUND_06_STRING;
                break;
            case 7:
                str = GROUP_BACKGROUND_07_STRING;
                break;
            case 8:
                str = GROUP_BACKGROUND_08_STRING;
                break;
            case 9:
                str = GROUP_BACKGROUND_09_STRING;
                break;
        }
        return str;
    }

    public static int getGroupBackgournResource(String s) {
        int rscID = R.color.gray;
        switch (s) {
            case GROUP_BACKGROUND_00_STRING:
                rscID = R.color.gray;
                break;
            case GROUP_BACKGROUND_01_STRING:
                rscID = R.drawable.bg_group_home_01;
                break;
            case GROUP_BACKGROUND_02_STRING:
                rscID = R.drawable.bg_group_home_02;
                break;
            case GROUP_BACKGROUND_03_STRING:
                rscID = R.drawable.bg_group_home_03;
                break;
            case GROUP_BACKGROUND_04_STRING:
                rscID = R.drawable.bg_group_home_04;
                break;
            case GROUP_BACKGROUND_05_STRING:
                rscID = R.drawable.bg_group_home_05;
                break;
            case GROUP_BACKGROUND_06_STRING:
                rscID = R.drawable.bg_group_home_06;
                break;
            case GROUP_BACKGROUND_07_STRING:
                rscID = R.drawable.bg_group_home_07;
                break;
            case GROUP_BACKGROUND_08_STRING:
                rscID = R.drawable.bg_group_home_08;
                break;
            case GROUP_BACKGROUND_09_STRING:
                rscID = R.drawable.bg_group_home_09;
                break;
        }

        return rscID;
    }

    public static Bitmap getCircleBitmap(int rscID) {
        return getCircleBitmap(((BitmapDrawable) IotPlatformApplication.getInstance().getApplicationContext().getDrawable(rscID)).getBitmap(),false);
    }

    public static Bitmap getCircleBitmap(Bitmap bitmap) {
        return getCircleBitmap(bitmap, false);
    }

    public static Bitmap getCircleBitmap(int rscID, boolean selected) {
        return getCircleBitmap(((BitmapDrawable) IotPlatformApplication.getInstance().getApplicationContext().getDrawable(rscID)).getBitmap(),selected);
    }

    public static Bitmap getCircleBitmap(Bitmap bitmap, boolean selected) {
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();

        if (width < height) {
            height = width;
        } else {
            width = height;
        }

        Bitmap outPut = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(outPut);


        final Rect rect = new Rect(2, 2, width - 2, height - 2);
        final RectF rectf = new RectF(rect);
        Paint paint = new Paint();
        paint.setAntiAlias(true);


        canvas.drawARGB(0, 0, 0, 0);
        canvas.drawArc(rectf, 0, 360, false, paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, paint);

        Paint drawLine = new Paint();
        drawLine.setAntiAlias(true);
        drawLine.setStyle(Paint.Style.STROKE);

        if(selected) {
            drawLine.setStrokeWidth(4);
            drawLine.setColor(0xFF271449);
        } else {
            drawLine.setStrokeWidth(2);
            drawLine.setColor(Color.TRANSPARENT);
        }

        canvas.drawArc(rectf, 0, 360, false, drawLine);
        return outPut;
    }

    public static String byteArrayToHex(byte[] a) {
        StringBuilder sb = new StringBuilder();
        for (final byte b : a)
            sb.append(String.format("%02x ", b & 0xff));
        return sb.toString();
    }

    public static String bssidToString(byte[] bssid) {
        StringBuilder sb = new StringBuilder(18);
        for (byte b : bssid) {
            if (sb.length() > 0)
                sb.append(':');
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }

    public static  byte[] appendByteArray(byte[] protocol, byte[] mac, int position) {
        byte[] temp = new byte[protocol.length];
        System.arraycopy(protocol, 0, temp, 0, protocol.length);
        System.arraycopy(mac, 0, temp, position, mac.length);
        return temp;
    }

    public static void showNotiMsg(Activity activity, String msg) {
        showNotiMsg(activity, msg, false);
    }
    public static void showNotiMsg(Activity activity, String msg, boolean isExist) {
        /*
        Snackbar snackbar = Snackbar.make(activity.findViewById(android.R.id.content),msg,Snackbar.LENGTH_LONG);
        if(isExist) {
            snackbar.addCallback(new Snackbar.Callback() {
                @Override
                public void onDismissed(Snackbar snackbar, int event) {
                    if (event == DISMISS_EVENT_TIMEOUT) {
                        // Some work to be done.
                        activity.finish();
                    }
                }
            });
        }
        snackbar.show();
         */
        activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                LayoutInflater inflater = activity.getLayoutInflater();
                View toastDesign = inflater.inflate(R.layout.custom_toast, null/*activity.findViewById(R.id.layoutToast)*/);

                TextView text = toastDesign.findViewById(R.id.txt);
                text.setText(msg); // toast_design.xml 파일에서 직접 텍스트를 지정 가능

                Toast toast = new Toast(activity);
                toast.setGravity(Gravity.BOTTOM | Gravity.HORIZONTAL_GRAVITY_MASK, 0, 0);
                toast.setDuration(Toast.LENGTH_SHORT);
                toast.setView(toastDesign);
                toast.show();
                if(isExist) {
                    activity.setResult(RESULT_OK);
                    activity.finish();
                }
            }
        });
    }

    public static void showNotiMsg(Activity activity, String msg, Class<?> cls) {
        /*
        Snackbar snackbar = Snackbar.make(activity.findViewById(android.R.id.content),msg,Snackbar.LENGTH_LONG);
        snackbar.addCallback(new Snackbar.Callback() {

            @Override
            public void onDismissed(Snackbar snackbar, int event) {
                if (event == DISMISS_EVENT_TIMEOUT) {
                    // Some work to be done.
                    Intent intent = new Intent(activity, cls);
                    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK
                            | Intent.FLAG_ACTIVITY_NEW_TASK);
                    activity.startActivity(intent);
                }
            }
        });
        snackbar.show();
         */
        activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                LayoutInflater inflater = activity.getLayoutInflater();
                View toastDesign = inflater.inflate(R.layout.custom_toast, null);

                TextView text = toastDesign.findViewById(R.id.txt);
                text.setText(msg); // toast_design.xml 파일에서 직접 텍스트를 지정 가능

                Toast toast = new Toast(activity);
                toast.setGravity(Gravity.BOTTOM | Gravity.HORIZONTAL_GRAVITY_MASK, 0, 0);
                toast.setDuration(Toast.LENGTH_SHORT);
                toast.setView(toastDesign);
                toast.show();

                Intent intent = new Intent(activity, cls);
                intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK
                        | Intent.FLAG_ACTIVITY_NEW_TASK);
                activity.startActivity(intent);
            }
        });
    }

    public static void showNotiMsg(final Activity activity, String msg, final Class<?> cls, final int flag) {
        /*
        Snackbar snackbar = Snackbar.make(activity.findViewById(android.R.id.content),msg,Snackbar.LENGTH_LONG);
        snackbar.addCallback(new Snackbar.Callback() {
            @Override
            public void onDismissed(Snackbar snackbar, int event) {
                if (event == DISMISS_EVENT_TIMEOUT) {
                    // Some work to be done.
                    Intent intent = new Intent(activity, cls);
                    intent.setFlags(flag);
                    activity.startActivity(intent);
                }
            }
        });
        snackbar.show();
         */

        activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                LayoutInflater inflater = activity.getLayoutInflater();
                View toastDesign = inflater.inflate(R.layout.custom_toast, null);

                TextView text = toastDesign.findViewById(R.id.txt);
                text.setText(msg); // toast_design.xml 파일에서 직접 텍스트를 지정 가능

                Toast toast = new Toast(activity);
                toast.setGravity(Gravity.BOTTOM | Gravity.HORIZONTAL_GRAVITY_MASK, 0, 0);
                toast.setDuration(Toast.LENGTH_SHORT);
                toast.setView(toastDesign);
                toast.show();

                Intent intent = new Intent(activity, cls);
                intent.setFlags(flag);
                activity.startActivity(intent);
            }
        });
    }

    public static void requestConfirmUser(Activity activity) {
        try {
            displayProgress(activity, "","");
            HttpApi.requestConfirmUser(true, true, UserInfo.email, new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    e.printStackTrace();
                    ErrorLogOutput(TAG, "HttpApi.requestConfirmUser(onFailure)\n" + e.toString());
                    showNotiMsg(activity, "인증 이메일 전송 요청에 실패하였습니다.");
                    DismissConnectDialog();
                    goToLoginActivity(activity);
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    if(response.code() == HttpApi.HTTP_NO_CONTENT) {
                        WarnLogOutput(TAG, "HttpApi.requestConfirmUser(onResponse) HTTP_NO_CONTENT");
                        showNotiMsg(activity, "인증 이메일 전송을 요청을 하였습니다.");
                        goToLoginActivity(activity);
                    } else {
                        ErrorLogOutput(TAG, "HttpApi.requestConfirmUser(onResponse) Error code : " + response.code() + "\nresponse : " + response.toString());
                        showNotiMsg(activity, "인증 이메일 전송 요청에 실패하였습니다.");
                        try {
                            JSONObject json_data = new JSONObject(response.body().string());
                            ErrorLogOutput(TAG, "HttpApi.requestConfirmUser(onResponse) body : " + json_data.toString());
                        } catch (JSONException e) {
                            ErrorLogOutput(TAG, "HttpApi.requestConfirmUser(onResponse) JSONException : " + e.toString());
                        }
                    }
                    DismissConnectDialog();
                    goToLoginActivity(activity);
                }
            });
        } catch (Exception e){
            e.printStackTrace();
            ErrorLogOutput(TAG, "HttpApi.requestConfirmUser(Exception)\n" + e.toString());
            showNotiMsg(activity, "인증 이메일 전송 요청에 실패하였습니다.");
            DismissConnectDialog();
            goToLoginActivity(activity);
        }
    }

    public static void sendConfirmEmail(Activity activity) {
        Intent intent = new Intent(activity, PopupActivity.class);
        intent.putExtra(PopupActivity.POPUP_MODE, PopupActivity.MODE_NORMAL);
        intent.putExtra(PopupActivity.POPUP_TITLE_TEXT, "이메일 인증이 진행되지 않았습니다. 이메일 인증후 서비스를 이용해주시기 바랍니다.");
        intent.putExtra(PopupActivity.POPUP_OK_BUTTON_TEXT, "이메일 인증 받기");
        activity.startActivityForResult(intent, RESULT_RESEND_CONFIRM);
    }

    public static void goToLoginActivity(Activity activity){
        putBoolean(AUTO_LOGIN, DEFAULT_AUTO_LOGIN);
        Intent intent;
        intent = new Intent(activity, LoginActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
        activity.startActivity(intent);
        activity.finish();
    }

    public static boolean isSupportedBluetooth(Context mContext){
        return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
    }

    @SuppressLint("MissingPermission")
    public static boolean isBluetoothToggle(Context mContext){
        final BluetoothManager bluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
        if(bluetoothManager == null || bluetoothManager.getAdapter() == null){
            return false;
        }
        return bluetoothManager.getAdapter().isEnabled();
    }


    //Check BlueTooth is Enalbe or not.
    public static boolean isBlueToothEnable(Context mContext){
        boolean isBluetooth = isBluetoothToggle(mContext);
        if (isSupportedBluetooth(mContext)) {
            if (!isBluetooth ) {
                return isBluetooth;
            }
        } else {
            Toast.makeText(mContext, R.string.bt_not_support_str, Toast.LENGTH_SHORT).show();
        }
        return isBluetooth;
    }

    public static boolean isExpiredSession() {
        DebugLogOutput(TAG, "로그인 후 시간(초) : " + ((System.currentTimeMillis()- getLong(LOGIN_TIME, DEFAULT_LOGIN_TIME))/1000));
        if (((getLong(LOGIN_TIME, DEFAULT_LOGIN_TIME) / 1000) + (60 * 50)) > (System.currentTimeMillis()/1000)) {
            return false; //not expired
        } else {
            DebugLogOutput(TAG, "Cognito token expired");
            return true; //expired
        }
    }

    public static void getCognitoSession(GetSessionCallback callback) {
        final AuthenticationHandler authenticationHandler = new AuthenticationHandler() {
            @Override
            public void onSuccess(CognitoUserSession cognitoUserSession, CognitoDevice device) {
                DebugLogOutput(TAG, " -- Auth Success");
                SharedPrefUtil.putLong(LOGIN_TIME, System.currentTimeMillis());
                AppHelper.setCurrSession(cognitoUserSession);
                AppHelper.newDevice(device);
                if(callback != null) {
                    callback.successed();
                }
            }

            @Override
            public void getAuthenticationDetails(AuthenticationContinuation authenticationContinuation, String userId) {

            }

            @Override
            public void getMFACode(MultiFactorAuthenticationContinuation continuation) {

            }

            @Override
            public void authenticationChallenge(ChallengeContinuation continuation) {

            }

            @Override
            public void onFailure(Exception e) {
                DebugLogOutput(TAG, " -- Auth Failed");
                if(callback != null) {
                    callback.failed();
                }
            }
        };

        CognitoUser user = AppHelper.getPool().getCurrentUser();
        final String username = user.getUserId();
        if(username != null) {
            AppHelper.setUser(username);
            user.getSessionInBackground(authenticationHandler);
        }
    }

    /**
     * 백그라운드 대기 시간 초기화 함수
     */
    public static void resetBackgroundWaitTime() {
        putLong(BACKGROUND_WAIT_TIME, DEFAULT_BACKGROUND_WAIT_TIME);
    }

    /**
     * 백그라운드 진입시 시간설정.
     */
    public static void setBackgroundWaitTime() {
        putLong(BACKGROUND_WAIT_TIME, System.currentTimeMillis());
    }

    /**
     * 앱 재시작 여부 확인 함수
     * @return
     */
    public static boolean isRestartAppForBackgroundWaitTime() {
        boolean result = false;
        long backgroundWaitTime = getLong(BACKGROUND_WAIT_TIME, DEFAULT_BACKGROUND_WAIT_TIME);
        if(backgroundWaitTime == 0) {
            result =  false;
        } else if((backgroundWaitTime+BACKGROUND_WAIT_EXIT_TIME) < System.currentTimeMillis()){
            result = true;
        }
        resetBackgroundWaitTime();
        return result;
    }

    /**
     * 앱 재시작 함수
     * @param activity
     */
    public static void restartApp(Activity activity) {
        /*
        Intent mStartActivity = new Intent(activity, SplashActivity.class);
        int mPendingIntentId = 123456;
        PendingIntent mPendingIntent = PendingIntent.getActivity(context, mPendingIntentId,    mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
        AlarmManager mgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
        mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
        System.exit(0);
        */
        Intent intent = new Intent(activity, SplashActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
        activity.startActivity(intent);
        activity.finish();
    }
}
