package com.rdiot.yx485

import android.app.Application
import android.view.View
import com.clj.fastble.BleManager
import com.drake.brv.utils.BRV
import com.drake.net.NetConfig
import com.drake.net.cookie.PersistentCookieJar
import com.drake.net.interceptor.LogRecordInterceptor
import com.drake.net.interfaces.NetErrorHandler
import com.drake.net.okhttp.setConverter
import com.drake.net.okhttp.setDebug
import com.drake.net.okhttp.setDialogFactory
import com.drake.net.okhttp.setErrorHandler
import com.drake.net.okhttp.setRequestInterceptor
import com.drake.net.utils.TipUtils
import com.drake.net.utils.scopeNet
import com.drake.tooltip.dialog.BubbleDialog
import com.jeremyliao.liveeventbus.LiveEventBus
import com.king.zxing.util.LogUtils
import com.lindroy.iosdialog.IDialog
import com.rdiot.yx485.base.ApiHost
import com.rdiot.yx485.base.LocalData
import com.rdiot.yx485.net.MyRequestInterceptor
import com.rdiot.yx485.net.SerializationConverter
import com.rdiot.yx485.net.appInit
import com.rdiot.yx485.net.checkVersion
import com.rdiot.yx485.ui.login.LoginActivity
import com.scwang.smart.refresh.footer.ClassicsFooter
import com.scwang.smart.refresh.header.MaterialHeader
import com.scwang.smart.refresh.layout.SmartRefreshLayout
import com.tencent.mmkv.MMKV
import com.tencent.mmkv.MMKVLogLevel
import dagger.hilt.android.HiltAndroidApp
import okhttp3.Cache
import java.util.concurrent.TimeUnit

const val TAG = "YongXu485"

/**
 *
 * @author mR2hao
 * @date 2022/11/10
 */
@HiltAndroidApp
class MyApp : Application() {

    companion object {
        lateinit var instance: MyApp
    }

    init {
        instance = this
    }

    override fun onCreate() {
        super.onCreate()

        // 初始化网络
        initNet()
        initBRV()
        // MMKV初始化
        MMKV.initialize(
            this,
            if (BuildConfig.DEBUG) MMKVLogLevel.LevelDebug else MMKVLogLevel.LevelNone
        )

        // 初始化蓝牙库
        BleManager.getInstance().init(this)
        // 初始化Dialog
        IDialog.init(this)


    }


    private fun initBRV() {
        BRV.modelId = BR.vm

        SmartRefreshLayout.setDefaultRefreshHeaderCreator { context, _ ->
            MaterialHeader(context)
        }
        SmartRefreshLayout.setDefaultRefreshFooterCreator { context, _ ->
            ClassicsFooter(context)
        }
    }

    private fun initNet() {
        val apiHost = LocalData.apiHost
        if (apiHost == ApiHost.TEST_HOST) {
            TipUtils.toast("注意，当前为${apiHost.hostName}")
        }

        NetConfig.initialize(apiHost.host, this) {

            // 超时设置
            connectTimeout(30, TimeUnit.SECONDS)
            readTimeout(30, TimeUnit.SECONDS)
            writeTimeout(30, TimeUnit.SECONDS)
            // 本框架支持Http缓存协议和强制缓存模式
            cache(Cache(cacheDir, 1024 * 1024 * 128)) // 缓存设置, 当超过maxSize最大值会根据最近最少使用算法清除缓存来限制缓存大小
            // LogCat是否输出异常日志, 异常日志可以快速定位网络请求错误
            setDebug(BuildConfig.DEBUG)
            // AndroidStudio OkHttp Profiler 插件输出网络日志
            addInterceptor(LogRecordInterceptor(BuildConfig.DEBUG))
            // 添加持久化Cookie管理
            cookieJar(PersistentCookieJar(this@MyApp))
            setRequestInterceptor(MyRequestInterceptor())
            // 数据转换器
            setConverter(SerializationConverter())
            setDialogFactory { // 全局加载对话框
                BubbleDialog(it)
            }
        }

        NetConfig.initialize(apiHost.host, this) {
            setErrorHandler(object : NetErrorHandler {
                override fun onError(e: Throwable) {
                    super.onError(e)
                    LogUtils.e("onError: ${e.message}")

                    if (e.message == "令牌失效") {
                        LiveEventBus.get(LoginActivity.TOKEN_INVALID, String::class.java)
                            .post(LoginActivity.TOKEN_INVALID)
                    } else if (e.message?.contains("failed to connect to") == true) {
                        TipUtils.toast("连接服务器失败")
                    } else {
                        TipUtils.toast(e.message)
                    }
                }

                override fun onStateError(e: Throwable, view: View) {
                    super.onStateError(e, view)
                    LogUtils.e("onStateError: ${e.message}")
                }
            })
        }

        scopeNet {
            appInit().await().apply { LogUtils.d("网络接口初始化成功") }

            scopeNet {
                checkVersion().await().apply {
                    LocalData.appVersionData.postValue(this)
                }
            }.catch { e ->
                LogUtils.e("获取版本信息失败:${e.message}")
            }

        }.catch { e ->
            LogUtils.e("网络接口初始化失败:${e.message}")
        }

    }

}