package com.sensetime.demo;

import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;

import com.orhanobut.logger.AndroidLogAdapter;
import com.orhanobut.logger.Logger;
import com.orhanobut.logger.SingLineFormatStrategy;
import com.sensetime.mtc.BuildConfig;
import com.sensetime.mtc.MClient;
import com.sensetime.mtc.MtcCode;
import com.squareup.leakcanary.LeakCanary;
import com.squareup.leakcanary.RefWatcher;

import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.util.Stack;

import kr.co.icontrols.ilp300_700.MainActivity;
import kr.co.icontrols.ilp300_700.R;

/**
 * Author:Created by LaoTie on 2019/12/12.
 * Enterprise:SenseTime
 **/
public class SenseTimeApp extends Application {

    private MClient mClient = MClient.getInstance();
    private SenseTimeMtc senseTimeMtc = SenseTimeMtc.getInstance();

    private CheckConnectRunnable checkConnectRunnable = new CheckConnectRunnable();
    private Thread checkConnectThread = new Thread(checkConnectRunnable);


    public static int FIRST_ACTIVITY_CREATED_NUM = 0;

    public static int SENSTIME_ERROR_REBOOT_COUNT = 5;
    private Stack<WeakReference<Activity>> activityList = new Stack<WeakReference<Activity>>();
    public static String MRROCONFIG_SP;

    private SparseArray<String> selectedImagePaths;
    private RefWatcher refWatcher;
    //public static String TAG = "SenseTimeApp";

    @Override
    public void onCreate() {
        super.onCreate();
        initLogger();
        Logger.e("onCreate START");
        FIRST_ACTIVITY_CREATED_NUM = 0;


        if (LeakCanary.isInAnalyzerProcess(this)) {
            // This process is dedicated to LeakCanary for heap analysis.
            // You should not init your app in this process.
            Logger.e("onCreate error");
            return;
        }
        refWatcher = LeakCanary.install(this);

        checkConnectThread.start();
        Logger.e("onCreate CLOSE");
    }


    private class CheckConnectRunnable implements Runnable {

        @Override
        public void run() {
            while (true) {
                String dev = senseTimeMtc.getDevicePath();
                if (!TextUtils.isEmpty(dev)) {//note 有节点
                    MtcCode mtcCode = mClient.mtcPing();
                    //Log.d("CheckConnectRunnable", "[CheckConnectRunnable] mtcCode:" + mtcCode);
                    if (mtcCode != MtcCode.SUCCESS) {//ping失败了，串口有问题，试图重连
                        senseTimeMtc.initMtc(() -> {
                        });

                        if(FIRST_ACTIVITY_CREATED_NUM == SENSTIME_ERROR_REBOOT_COUNT)
                            MainActivity.mIOInterface.Reboot(0);

                        FIRST_ACTIVITY_CREATED_NUM++;
                    }
                    else
                    {
                        FIRST_ACTIVITY_CREATED_NUM = 5;
                    }
                }

                String strState = get("SenseTimeActive");

                if (strState.equals("end2"))
                {
                    set("SenseTimeActive", "default");
                    Intent intent = new Intent();
                    intent.setAction("SENSETIME_ERROR");
                    sendBroadcast(intent);
                }

                try {
                    //Thread.sleep(1000 * 3);
                    Thread.sleep(1000 * 3); // 1초마다 연결상태 확인
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static String get(String key) {
        String ret = "";
        try {
            Class<?> SystemProperties = Class.forName("android.os.SystemProperties");
            //Parameters Types
            @SuppressWarnings("rawtypes")
            Class[] paramTypes = { String.class };
            Method get = SystemProperties.getMethod("get", paramTypes);

            //Parameters
            Object[] params = { key };
            ret = (String) get.invoke(SystemProperties, params);
        } catch (IllegalArgumentException e) {
            ret = ""; e.printStackTrace();
            Log.e("SenseTimeApp", "IllegalArgumentException e: "+e.toString());
        } catch (Exception e) {
            ret = "";
            e.printStackTrace();
            Log.e("SenseTimeApp", "Exception e: "+e.toString());
        }
        return ret;
    }

    public static void set(String key, String val) throws IllegalArgumentException {
        try {
            Class<?> SystemProperties = Class.forName("android.os.SystemProperties");

            //Parameters Types
            @SuppressWarnings("rawtypes")
            Class[] paramTypes = { String.class, String.class };
            Method set = SystemProperties.getMethod("set", paramTypes);

            //Parameters
            Object[] params = { key, val };
            set.invoke(SystemProperties, params);
        }
        catch (IllegalArgumentException e) {
            e.printStackTrace();
            Log.e("SenseTimeApp", "IllegalArgumentException e: "+e.toString());
        }
        catch (Exception e) {
            e.printStackTrace();
            Log.e("SenseTimeApp", "IllegalArgumentException e: "+e.toString());
        }
    }


    /**
     * 根据不同的版本初始化日志模块
     */
    private void initLogger() {
        int logPriority = Log.VERBOSE;
        if (!BuildConfig.DEBUG) {
            logPriority = Log.ERROR;
        }
        Logger.addLogAdapter(new AndroidLogAdapter(SingLineFormatStrategy.newBuilder()
                .priority(logPriority)
                .showMethod(true)
                .showThreadInfo(true)
                .tag(getString(R.string.app_name))
                .build()));
    }

    /**
     * 将Activity压入Application栈
     *
     * @param task 将要压入栈的Activity对象
     */
    public void pushTask(WeakReference<Activity> task) {
        int index = activityList.indexOf(task);
        activityList.push(task);
    }

    /**
     * 将传入的Activity对象从栈中移除
     *
     * @param task
     */
    public void removeTask(WeakReference<Activity> task) {
        activityList.remove(task);
    }

    @Override
    public void onTerminate() {
        Logger.e("onTerminate");
        super.onTerminate();
        MClient.getInstance().mtcDestroy();
    }

    public void exitApp() {
        for (WeakReference<Activity> task : activityList) {
            Activity activity = task.get();
            if (activity != null && !activity.isFinishing()) {
                activity.finish();
            }
        }
        System.exit(0);
    }

    public static RefWatcher getRefWatcher(Context context) {
        SenseTimeApp senseTimeApp = (SenseTimeApp) context.getApplicationContext();
        return senseTimeApp.refWatcher;
    }

    public SparseArray<String> getSelectedImagePaths() {
        return selectedImagePaths;
    }

    public void setSelectedImagePaths(SparseArray<String> selectedImagePaths) {
        this.selectedImagePaths = selectedImagePaths;
    }
}
