package com.wdkl.lcd_board.helper;

import android.app.Application;
import android.os.Environment;
import android.util.Log;

import com.github.anrwatchdog.ANRError;
import com.github.anrwatchdog.ANRWatchDog;

import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;

/**
 * Created by dengzhe on 2018/4/2.
 * //=========================FC&ANR异常处理类=========================//
 */

public class AnrFcExceptionUtil implements Thread.UncaughtExceptionHandler {

    private static ANRWatchDog mANRWatchDog;
    private Thread.UncaughtExceptionHandler mDefaultHandler;
    public static final String TAG = "MyApplication";
    private static Application application;

    private static AnrFcExceptionUtil mAnrFcExceptionUtil;

    /**
     * 存储异常和参数信息
     */
    private Map<String, String> paramsMap = new HashMap<>();
    /**
     * 格式化时间
     */
    private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");


    public static AnrFcExceptionUtil getInstance(Application application) {
        if (mAnrFcExceptionUtil == null) {
            mAnrFcExceptionUtil = new AnrFcExceptionUtil(application);
        }
        return mAnrFcExceptionUtil;
    }

    private AnrFcExceptionUtil(Application application) {
        //获取系统默认的UncaughtException处理器
        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
        this.application = application;
    }

    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        if (!handleException(ex) && mDefaultHandler != null) {
            //如果用户没有处理则让系统默认的异常处理器来处理
            mDefaultHandler.uncaughtException(thread, ex);
        } else {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                Log.e(TAG, "error : ", e);
            }

            AppUpdateHelper.restartApp(application);
            //android.os.Process.killProcess(android.os.Process.myPid());
            //System.exit(0);
        }
    }

    /**
     * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
     *
     * @param ex
     * @return true:如果处理了该异常信息;否则返回false.
     */
    private boolean handleException(Throwable ex) {
        if (ex == null) {
            return false;
        }
        //使用Toast来显示异常信息
        /*new Thread() {
            @Override
            public void run() {
                Looper.prepare();
//                Toast.makeText(application.getApplicationContext(), "很抱歉,程序出现异常,即将重新启动.",
//                        Toast.LENGTH_SHORT).show();
                Looper.loop();
            }
        }.start();*/
        saveCrashInfo2File(ex);
        return true;
    }

    /**
     * 保存错误信息到文件中
     *
     * @param ex
     * @return 返回文件名称
     */
    private String saveCrashInfo2File(Throwable ex) {
        StringBuffer sb = new StringBuffer();
        for (Map.Entry<String, String> entry : paramsMap.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            sb.append(key + "=" + value + "\n");
        }

        Writer writer = new StringWriter();
        PrintWriter printWriter = new PrintWriter(writer);
        ex.printStackTrace(printWriter);
        Throwable cause = ex.getCause();
        while (cause != null) {
            cause.printStackTrace(printWriter);
            cause = cause.getCause();
        }
        printWriter.close();
        String result = writer.toString();
        sb.append(result);

        try {
            long timestamp = System.currentTimeMillis();
            String time = format.format(new Date());
            format.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
            String fileName = "crash-" + time + "-" + timestamp + ".txt";
            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/crash/";
                File dir = new File(path);
                if (!dir.exists()) {
                    dir.mkdirs();
                }
                FileOutputStream fos = new FileOutputStream(path + fileName);
                fos.write(sb.toString().getBytes());
                Log.i(TAG, "saveCrashInfo2File: "+sb.toString());
                fos.close();
            }
            return fileName;
        } catch (Exception e) {
            Log.e(TAG, "an error occured while writing file...", e);
        }
        return null;
    }

    /**
     * ===================================================崩溃异常处理===================================================
     */
    public void initFCException() {
        //设置该CrashHandler为程序的默认处理器
        AnrFcExceptionUtil catchExcep = AnrFcExceptionUtil.getInstance(application);
        Thread.setDefaultUncaughtExceptionHandler(catchExcep);
        mANRWatchDog = new ANRWatchDog(8000);
        mANRWatchDog.setInterruptionListener(new ANRWatchDog.InterruptionListener() {
            @Override
            public void onInterrupted(InterruptedException exception) {
            }
        }).setIgnoreDebugger(true).setANRListener(new ANRWatchDog.ANRListener() {
            @Override
            public void onAppNotResponding(ANRError error) {
                /*Intent mStartActivity = new Intent(application.getApplicationContext(), Constants.ANR_FC);
                int mPendingIntentId = 123456;
                PendingIntent mPendingIntent = PendingIntent.getActivity(application.getApplicationContext(), mPendingIntentId, mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
                AlarmManager mgr = (AlarmManager) application.getApplicationContext().getSystemService(Context.ALARM_SERVICE);
                mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1500, mPendingIntent);
                android.os.Process.killProcess(android.os.Process.myPid());*/

                Log.d("anr", "Anr restart app...");
                AppUpdateHelper.rebootDevice();
            }
        }).start();

    }
}
