package com.auparty.android.crashguard

import android.annotation.SuppressLint
import android.content.Context
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.util.Log
import com.auparty.android.crashguard.compat.*
import me.weishu.reflection.Reflection

/**
 * @author SimonHou
 * @description:
 * @date :2023/4/28 16:36
 */
object CrashGuard {
    //当异常发生在生命周期的时候 会调用此对象杀死发生异常的Activity
    private var sActivityKiller: IActivityKiller? = null
    private var mExceptionHandler: ExceptionHandler? = null

    //判断是否已经装在崩溃防护组件
    private var sInstalled: Boolean = false

    fun install(ctx: Context, exceptionHandler: ExceptionHandler) {
        if (sInstalled) {
            return
        }
        try {
            Reflection.unseal(ctx)
        } catch (throwable: Throwable) {
            throwable.printStackTrace()
        }
        sInstalled = true
        mExceptionHandler = exceptionHandler
        //根据不同的的API版本装载不同的ActivityKiller
        initActivityKiller()
        Thread.setDefaultUncaughtExceptionHandler { p0, p1 ->
            Log.e("simon", "111111111111111")
            mExceptionHandler?.uncaughtException(p0, p1)
            Log.e("simon", "2222222222")

        }
        Log.e("simon", "33333333")
        Handler(ctx.mainLooper).post {
            while (true) {
                try {
                    Log.e("simon", "4444444")
                    Looper.loop()
                    Log.e("simon", "555555")
                } catch (e: Throwable) {
                    Log.e("simon", "7777")
                    mExceptionHandler?.uncaughtException(Looper.getMainLooper().thread, e)
                    Log.e("simon", "8888")
                }
            }
        }

    }

    private fun initActivityKiller() {
        val sdkVersion = Build.VERSION.SDK_INT
        sActivityKiller = if (sdkVersion >= 28) {
            ActivityKillerV28()
        } else if (sdkVersion >= 26) {
            ActivityKillerV26()
        } else if (sdkVersion == 25 || sdkVersion == 24) {
            ActivityKillerV24_V25()
        } else if (sdkVersion in 21..23) {
            ActivityKillerV21_V23()
        } else {
            ActivityKillerV15_V20()
        }

        try {
            //反射注入自己的callBack拦截处理系统的Handler消息
            setHCallBack()
        } catch (e: Throwable) {
            e.printStackTrace()
        }
    }

    @SuppressLint("PrivateApi", "DiscouragedPrivateApi")
    private fun setHCallBack() {
        val launchActivity = 100
        val pauseActivity = 101
        val pauseActivityFinishing = 102
        val stopActivityHide = 104
        val resumeActivity = 107
        val destroyActivity = 109
        val executeTransaction = 159

        val activityThreadClass = Class.forName("android.app.ActivityThread")
        val activityThread =
            activityThreadClass.getDeclaredMethod("currentActivityThread").invoke(null)
        val mHField = activityThreadClass.getDeclaredField("mH")
        mHField.isAccessible = true
        val mhHandler = mHField.get(activityThread) as Handler
        val callbackField = Handler::class.java.getDeclaredField("mCallback")
        callbackField.isAccessible = true
        callbackField.set(mhHandler, object : Handler.Callback {
            override fun handleMessage(msg: Message): Boolean {
                if (Build.VERSION.SDK_INT >= 28) { //android P 生命周期全部走这
                    if (msg.what == executeTransaction) {
                        try {
                            mhHandler.handleMessage(msg)
                        } catch (throwable: Throwable) {
                            sActivityKiller?.finishLaunchActivity(msg)
                            lifeCycleException(throwable, msg.what)
                        }
                        return true
                    }
                    return false
                }
                //以下生命周期都是针对android P以下的代码
                when (msg.what) {
                    launchActivity -> {
                        try {
                            mhHandler.handleMessage(msg)
                        } catch (throwable: Throwable) {
                            sActivityKiller?.finishLaunchActivity(msg)
                            lifeCycleException(throwable, msg.what)
                        }
                        return true
                    }
                    resumeActivity -> {
                        try {
                            mhHandler.handleMessage(msg)
                        } catch (throwable: Throwable) {
                            sActivityKiller?.finishResumeActivity(msg)
                            lifeCycleException(throwable, msg.what)
                        }
                        return true
                    }
                    pauseActivityFinishing -> {
                        try {
                            mhHandler.handleMessage(msg)
                        } catch (throwable: Throwable) {
                            sActivityKiller?.finishResumeActivity(msg)
                            lifeCycleException(throwable, msg.what)
                        }
                        return true
                    }
                    pauseActivity -> {
                        try {
                            mhHandler.handleMessage(msg)
                        } catch (throwable: Throwable) {
                            sActivityKiller?.finishPauseActivity(msg)
                            lifeCycleException(throwable, msg.what)
                        }
                        return true
                    }
                    stopActivityHide -> {
                        try {
                            mhHandler.handleMessage(msg)
                        } catch (throwable: Throwable) {
                            sActivityKiller?.finishStopActivity(msg)
                            lifeCycleException(throwable, msg.what)
                        }
                        return true
                    }
                    destroyActivity -> {
                        try {
                            mhHandler.handleMessage(msg)
                        } catch (throwable: Throwable) {
                            lifeCycleException(throwable, msg.what)
                        }
                        return true
                    }
                }
                return false
            }
        })

    }

    private fun lifeCycleException(throwable: Throwable, what: Int) {
        Log.e("notifyException", "--->notifyException: mH出错 生命周期:${what}")
        mExceptionHandler?.unCatchLifeCycleException(Looper.getMainLooper().thread, throwable)

    }
}