package com.develop.foodcooking

import android.annotation.SuppressLint
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.PowerManager
import android.os.PowerManager.WakeLock
import android.provider.Settings
import android.util.Log
import com.blankj.utilcode.util.AppUtils
import com.blankj.utilcode.util.LanguageUtils
import com.blankj.utilcode.util.PathUtils
import com.blankj.utilcode.util.ResourceUtils
import com.blankj.utilcode.util.Utils
import com.develop.food.base.FoodCookBaseApp
import com.develop.food.base.repo.FoodDataProvider
import com.develop.food.base.router.ARouterUtils
import com.develop.food.base.utils.*
import com.kuyuntech.cofarcooking.device.sdk.constant.core.BaseConfig
import com.kuyuntech.cofarcooking.device.sdk.constant.core.DevStatus
import com.kuyuntech.cofarcooking.device.sdk.eventbus.event.DevStatusEvent
import com.kuyuntech.cofarcooking.device.sdk.util.core.CofarSDK
import com.tencent.bugly.crashreport.CrashReport
import org.alee.component.skin.compat.ConstraintLayoutCompat
import org.alee.component.skin.page.WindowManager
import org.alee.component.skin.service.Config
import org.alee.component.skin.service.IOptionFactory
import org.alee.component.skin.service.IThemeSkinOption
import org.alee.component.skin.service.ThemeSkinService
import org.greenrobot.eventbus.Subscribe
import java.io.File
import java.lang.reflect.Method
import java.util.*


class FoodCookApp : FoodCookBaseApp() {
    var mWakeLock: PowerManager.WakeLock? = null

    companion object {
        init {
            Config.getInstance().skinMode = Config.SkinMode.REPLACE_ALL
            Config.getInstance().performanceMode = Config.PerformanceMode.EXPERIENCE_FIRST
            ConstraintLayoutCompat.init()
            RecyclerViewCompat.init()
        }
    }


    override fun onCreate() {
        //        收集崩溃问题
//        CatchException.getInstence().init(this)

        //处理webView xml报错问题
        hookWebView()
        super.onCreate()
        MmkvUtils.initialize(this)
        ARouterUtils.init(this, BuildConfig.DEBUG)
        CrashReport.initCrashReport(this, "0c1b27f35b", BuildConfig.DEBUG)
        ResourceUtils.copyFileFromAssets(
            ASSETS_NIGHT_SKIN_PACK, SKIN_PACK_PATH + NIGHT_SKIN_PACK_NAME
        )
        WindowManager.getInstance().init(this, OptionFactory())
        val isNight = BuildConfig.UpdatePlatform.equals("night")
        ThemeSkinService.getInstance().switchThemeSkin(if (isNight) 1 else 0)
        setNightTheme(isNight)
        BaseConfig.TEMP_OF_LIMIT_MOTOR = 0
        //初始化CofarSDK竖屏，因为DIY的配置跟横屏的不一致
        CofarSDK.init(BuildConfig.brandCode,BuildConfig.model)
//        CofarSDK.init(getBrandNum())
        SerialportUtils.init()
        CofarSDK.register(this)
        CofarSDK.stopNative()
        Thread {
            var isUpdateFile = StringUtils.doesUpdateTxtFileExist()
            //之前根据zip包的md5 更新，现在做一个文本获取进行更新， 先判断是否存在，存在再处理，不存在就走之前的方法
            Log.d("TAG update", "isUpdateFile  文件： $isUpdateFile")
            if (isUpdateFile) {
                Log.d("TAG update", "isUpdateFile  文件存在 ")
                var fileUpdate = StringUtils.getUpdateTime()
                var roomUpdate = getUpdateRecipeTime()

                Log.d("TAG update", "fileUpdate :   $fileUpdate")
                Log.d("TAG update", "roomUpdate :   $roomUpdate")


                FoodDataProvider.setUpdateTime(fileUpdate)
                //当本地时间为空，或者file的文件时间比本地时间大的时候，证明食谱包更新了
                if (roomUpdate == "" || fileUpdate.toLong() > roomUpdate.toLong()) {
                    Log.d("TAG update", "isUpdateFile1111111--------  文件存在 ")

                    //删除room数据库
                    deleteRoomDb()
                    //删除sd卡的东西
                    FoodDataProvider.deleteAll()
                    FoodDataProvider.prepareData(this)
                } else {
                    FoodDataProvider.prepareData(this)
                }
            }else{
                FoodDataProvider.prepareData(this)
            }
        }.start()
        val mContext = applicationContext
        val powerManager =
            mContext.getSystemService(android.content.Context.POWER_SERVICE) as PowerManager
        val wakeLock: WakeLock =
            powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "motionDetection:keepAwake")
        wakeLock.acquire()
        NetWorkManager.get().init(this)
        var minute = MmkvUtils.getInt("ScreenSaver")
        if (minute == 0) {
            minute = 3;
        }
        Settings.System.putInt(
            contentResolver, Settings.System.SCREEN_OFF_TIMEOUT, (1000 * 60 * minute).toInt()
        )
        val uri: Uri = Settings.System.getUriFor(Settings.System.SCREEN_OFF_TIMEOUT)
        contentResolver.notifyChange(uri, null)
    }

    var keepScreen = false

    var timer: Timer? = null;

    var ledLock = false;


    @SuppressLint("InvalidWakeLockTag")
    @Subscribe
    fun onTuyaEvent(event: TuyaEvent) {

        TuyaUtils.uploadData()
        val pm = getSystemService(POWER_SERVICE) as PowerManager

        if (mWakeLock == null) {
            mWakeLock = pm.newWakeLock(
                PowerManager.SCREEN_BRIGHT_WAKE_LOCK or PowerManager.ON_AFTER_RELEASE or PowerManager.ACQUIRE_CAUSES_WAKEUP,
                "tag"
            );
            mWakeLock?.setReferenceCounted(false);
            mWakeLock?.acquire()
        }

        mWakeLock?.release()
        mWakeLock = null
        val intent = Intent()
        intent.action = "android.intent.action.SS_DEVICE_TOUCH"
        sendBroadcast(intent)
    }


    @SuppressLint("InvalidWakeLockTag")
    @Subscribe
    @Synchronized
    fun devMsg(event: DevStatusEvent) {

//        return
        TuyaUtils.uploadData()

        val devInfo = event.devInfo;
        val pm = getSystemService(POWER_SERVICE) as PowerManager
        var minute = MmkvUtils.getInt("ScreenSaver")
        if (minute == 0) {
            minute = 3;
        }

        if (devInfo.status == DevStatus.RUNNING.toInt() || devInfo.isWeightStatus) {
            if (mWakeLock == null) {
                mWakeLock = pm.newWakeLock(
                    PowerManager.SCREEN_BRIGHT_WAKE_LOCK or PowerManager.ON_AFTER_RELEASE or PowerManager.ACQUIRE_CAUSES_WAKEUP,
                    "tag"
                );
                mWakeLock?.setReferenceCounted(false);
                mWakeLock?.acquire()
            }


        } else if (devInfo.status != DevStatus.RUNNING.toInt()) {
            if (mWakeLock != null) {
                mWakeLock?.release()
                mWakeLock = null
                val intent = Intent()
                intent.action = "android.intent.action.SS_DEVICE_TOUCH"
                sendBroadcast(intent)
            }

        }




        if (!ledLock) {
            ledLock = true;
            if (!pm.isScreenOn) {
                //errcode 为0得时候，是有故障
                //合盖
                if (event.devInfo.potStatus.toInt() == 0) {
                    if (event.devInfo.potCloverStatus.toInt() == 0) {
                        CofarSDK.flashWhiteRedLed()
                    } else {
                        CofarSDK.switchWhiteLed('0');
                        CofarSDK.flashRedLed()
                    }
                } else {
                    CofarSDK.switchWhiteLed('0');
                    CofarSDK.flashRedLed();
                }

            } else {
                if (devInfo.status == DevStatus.STOP.toInt()) {

                    if (devInfo.potStatus.toInt() == 0) {
                        if (devInfo.potCloverStatus.toInt() == 0) {
                            CofarSDK.flashWhiteRedLed()
                        } else {
                            CofarSDK.switchWhiteLed('0');
                            CofarSDK.flashRedLed()
                        }
                    } else {
                        CofarSDK.switchWhiteLed('0');
                        CofarSDK.flashRedLed();
                    }

                }

                if (devInfo.status == DevStatus.RUNNING.toInt()) {

                    if (devInfo.temp < 60) {
                        CofarSDK.switchRedLed('0');
                        CofarSDK.switchWhiteLed('1');
                    } else {
                        CofarSDK.switchRedLed('1');
                        CofarSDK.switchWhiteLed('0');
                    }

                }

                if (devInfo.status == DevStatus.PAUSE.toInt()) {

                    //判断盖子是否打开
                    //合盖
                    if (devInfo.potCloverStatus.toInt() == 1) {
                        CofarSDK.switchWhiteLed('0');
                        CofarSDK.flashRedLed()
                    } else {
                        CofarSDK.flashWhiteRedLed()
                    }


                }
            }
            ledLock = false;
        }



        println(pm.isScreenOn)

    }


}

class OptionFactory : IOptionFactory {
    override fun defaultTheme(): Int {
        return 0
    }

    override fun requireOption(theme: Int): IThemeSkinOption? {
        return when (theme) {
            1 -> NightOption()
            else -> null
        }
    }
}

fun hookWebView() {
    val TAG = "ASDD"
    val sdkInt = Build.VERSION.SDK_INT
    try {
        val factoryClass = Class.forName("android.webkit.WebViewFactory")
        val field = factoryClass.getDeclaredField("sProviderInstance")
        field.isAccessible = true
        var sProviderInstance = field[null]
        if (sProviderInstance != null) {
            Log.d(TAG, "sProviderInstance isn't null")
            return
        }
        val getProviderClassMethod: Method
        getProviderClassMethod = if (sdkInt > 22) {
            factoryClass.getDeclaredMethod("getProviderClass")
        } else if (sdkInt == 22) {
            factoryClass.getDeclaredMethod("getFactoryClass")
        } else {
            Log.d(TAG, "Don't need to Hook WebView")
            return
        }
        getProviderClassMethod.isAccessible = true
        val providerClass = getProviderClassMethod.invoke(factoryClass) as Class<*>
        val delegateClass = Class.forName("android.webkit.WebViewDelegate")
        val providerConstructor = providerClass.getConstructor(delegateClass)
        if (providerConstructor != null) {
            providerConstructor.isAccessible = true
            val declaredConstructor = delegateClass.getDeclaredConstructor()
            declaredConstructor.isAccessible = true
            sProviderInstance =
                providerConstructor.newInstance(declaredConstructor.newInstance())
            field["sProviderInstance"] = sProviderInstance
        }
        Log.d(TAG, "Hook done!")
    } catch (e: Throwable) {
    }
}

class NightOption : IThemeSkinOption {
    override fun getStandardSkinPackPath(): LinkedHashSet<String> {
        val pathSet = LinkedHashSet<String>()

        pathSet.add(SKIN_PACK_PATH + NIGHT_SKIN_PACK_NAME)
        return pathSet
    }
}

const val NIGHT_SKIN_PACK_NAME = "skins/night.skin"
const val ASSETS_NIGHT_SKIN_PACK = "skins/night.skin"

/**
 * 应用存储空间根路径
 */
private val ROOT_PATH =
    Utils.getApp().getExternalFilesDir(null)?.absolutePath?.run { this + File.separator }
        ?: (PathUtils.getExternalAppDataPath() + "." + AppUtils.getAppPackageName() + File.separator)

/**
 * 皮肤包根路径
 */
val SKIN_PACK_PATH = ROOT_PATH + ".SkinPack" + File.separator