package cn.muchinfo.rma.view

import android.app.Activity
import android.app.AlertDialog
import android.content.Context
import android.os.Bundle
import android.os.Looper
import cn.muchinfo.rma.BuildConfig
import cn.muchinfo.rma.business.account.AccountManager
import cn.muchinfo.rma.business.commodity.CommodityManager
import cn.muchinfo.rma.business.common.CommonManager
import cn.muchinfo.rma.business.contract.ContractManager
import cn.muchinfo.rma.business.customer.CustomerManage
import cn.muchinfo.rma.business.exposure.ExposureManager
import cn.muchinfo.rma.business.financial.FinancialManager
import cn.muchinfo.rma.business.future.FutureManager
import cn.muchinfo.rma.business.hedge.HedgeManager
import cn.muchinfo.rma.business.initialize.InitializeManager
import cn.muchinfo.rma.business.management.BusinessManager
import cn.muchinfo.rma.business.report.ReportManager
import cn.muchinfo.rma.business.tradingquery.TradingQueryManager
import cn.muchinfo.rma.global.GlobalDataCollection
import cn.muchinfo.rma.global.JsonUtils
import cn.muchinfo.rma.global.data.database.EnumDicEntity
import cn.muchinfo.rma.global.data.database.ErrorCodeEntity
import cn.muchinfo.rma.global.database.AppDatabase
import cn.muchinfo.rma.global.database.DataBase
import cn.muchinfo.rma.global.room.Builder
import cn.muchinfo.rma.netManage.base.interceptor.LoggingInterceptor
import cn.muchinfo.rma.netcore.packet.Packet40
import cn.muchinfo.rma.netcore.packet.Packet50
import cn.muchinfo.rma.netcore.socket.MTP2Socket
import cn.muchinfo.rma.netcore.socket.MTP2SocketListener
import cn.muchinfo.rma.protobuf.funcode.FunCode
import cn.muchinfo.rma.view.base.BaseApplication
import cn.muchinfo.rma.view.base.app.Constant
import com.blankj.utilcode.util.AppUtils
import com.blankj.utilcode.util.LogUtils
import com.blankj.utilcode.util.SPUtils
import com.blankj.utilcode.util.Utils
import com.facebook.drawee.backends.pipeline.Fresco
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.tencent.smtt.sdk.QbSdk
import com.tencent.smtt.sdk.QbSdk.PreInitCallback
import com.zhy.http.okhttp.OkHttpUtils
import com.zhy.http.okhttp.https.HttpsUtils
import okhttp3.OkHttpClient


class MyApplication : BaseApplication() {

    /** 行情链路 */
    var quoteSocketManager: MTP2Socket<Packet40>? = null

    /** 交易链路 */
    var tradeSocketManager: MTP2Socket<Packet50>? = null

    /** 账户管理 */
    var accountManager: AccountManager? = null

    /**
     * 客户资料管理
     */
    var customerManage: CustomerManage? = null

    /** 合同信息管理 */
    var contractManager: ContractManager? = null

    /** 套保信息管理类 */
    var hedgeManager: HedgeManager? = null

    /** 业务管理管理类 */
    var businessManager: BusinessManager? = null

    /** 商品信息管理类 */
    var commodityManager: CommodityManager? = null

    /** 通用的管理类 **/
    var commonManager: CommonManager? = null

    /** 财务管理类 **/
    var financialManager: FinancialManager? = null

    /** 当前页面的activity context **/
    var context: Context? = null

    /** 初始化数据的管理类 **/
    var initializeManager : InitializeManager? = null

    /** 敞口管理类 **/
    var exposureManager : ExposureManager? = null

    /** 交易查询相关管理类 **/
    var tradingQueryManager : TradingQueryManager? = null

    /** 报表查询相关管理类 **/
    var reportManager : ReportManager? = null

    /** 期货相关管理类 **/
    var futureManager : FutureManager? = null

    companion object {
        private var instance: MyApplication? = null

        fun getInstance(): MyApplication? {
            synchronized(MyApplication::class.java) {
                if (instance == null) {
                    synchronized(MyApplication::class.java) { return MyApplication() }
                }
            }
            return instance
        }
    }

    override fun onCreate() {
        super.onCreate()

        initManager()

        // 在OnCreate 中可以传入 自定义的 GlobalConfig
        /*MVVMLin.install(object : GlobalConfig {
            override fun viewModelFactory() = ViewModelFactory.getInstance()
        })*/
        instance = this
        LogUtils.getConfig().run {
            isLogSwitch = BuildConfig.DEBUG
            setSingleTagSwitch(true)
        }
        initX5()
        val sslParams = HttpsUtils.getSslSocketFactory(null, null, null)
        val okHttpClient = OkHttpClient.Builder()
            .addNetworkInterceptor(LoggingInterceptor())
            .sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager) //其他配置
            .build()
        OkHttpUtils.initClient(okHttpClient)

        Utils.init(instance)
        Fresco.initialize(this)
        Builder.build(this, AppDatabase::class.java)
        initLifecycle()
        initsqData()
    }

    /**
     * 对本地数据进行插入数据库操作，只在第一次启动app时有此操作
     */
    private fun initsqData(){
        if (SPUtils.getInstance().getBoolean(Constant.FISTOPENAPP,true)){
            /** 枚举dao **/
            val enumDao = DataBase.getInstance().enumsDicDao()
            /** 错误信息dao **/
            val errorCodeDao = DataBase.getInstance().errorCodeDao()
            /** 本地获取的错误信息jsonString **/
            val errorJsonList = JsonUtils.getJson(resources.assets.open("errormessage.json"))
            /** 本地获取的枚举jsonString **/
            val enumJsonList = JsonUtils.getJson(resources.assets.open("enums.json"))
            val gson = Gson()
            /** 解析错误信息json **/
            val errorTabDatas: List<ErrorCodeEntity> =
                gson.fromJson(errorJsonList, object : TypeToken<List<ErrorCodeEntity?>?>() {}.type)
            /** 解析枚举json **/
            val enumTabDatas: List<EnumDicEntity> =
                gson.fromJson(enumJsonList, object : TypeToken<List<EnumDicEntity?>?>() {}.type)
            /** 错误信息插入数据库 **/
            errorCodeDao.insert(errorTabDatas)

            /** 枚举插入数据库 **/
            enumDao.insert(enumTabDatas)
            SPUtils.getInstance().put(Constant.FISTOPENAPP,false)
        }
        GlobalDataCollection.instance?.errorCodeEntityList = DataBase.getInstance().errorCodeDao().getList()
        GlobalDataCollection.instance?.enumDicEntityList = DataBase.getInstance().enumsDicDao().getList()
    }

    private fun initManager() {
        quoteSocketManager = MTP2Socket<Packet40>(0, quoteSocketListener)
        tradeSocketManager = MTP2Socket<Packet50>(1, tradeSocketListener)

        accountManager = AccountManager()
        customerManage = CustomerManage()
        contractManager = ContractManager()
        hedgeManager = HedgeManager()
        businessManager = BusinessManager()
        commodityManager = CommodityManager()
        commonManager = CommonManager()
        financialManager = FinancialManager()
        initializeManager = InitializeManager()
        exposureManager = ExposureManager()
        tradingQueryManager = TradingQueryManager()
        reportManager = ReportManager()
        futureManager = FutureManager()
    }

    /**
     * 退出应用，并显示登录界面
     */
    fun exitApp() {
        // 退出应用
//        val intent = instance?.packageManager
//            ?.getLaunchIntentForPackage(instance?.packageName!!)
//        intent!!.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
//        ActivityUtils.startActivity(intent)
//        AppUtils.exitApp()
        AppUtils.relaunchApp()
        // TODO: - 显示登录界面
    }

    private fun initX5() {
        val cb: PreInitCallback = object : PreInitCallback {
            override fun onViewInitFinished(arg0: Boolean) {
                // TODO Auto-generated method stub
                //x5內核初始化完成的回调，为true表示x5内核加载成功，否则表示x5内核加载失败，会自动切换到系统内核。
                LogUtils.eTag("app", " onViewInitFinished is $arg0")
            }

            override fun onCoreInitFinished() {
                // TODO Auto-generated method stub
            }
        }
        //x5内核初始化接口
        QbSdk.initX5Environment(applicationContext, cb)
    }

    /** 行情链路回调 */
    val quoteSocketListener = object : MTP2SocketListener<Packet40> {
        override fun onConnected(socket: MTP2Socket<Packet40>?) {

        }

        override fun onClosed(socket: MTP2Socket<Packet40>?) {

        }

        override fun onError(socket: MTP2Socket<Packet40>?, err: Error?) {

        }

        override fun onReceivePush(socket: MTP2Socket<Packet40>?, data: Packet40?) {

        }

        override fun onReconnectChangeState(socket: MTP2Socket<Packet40>?, state: Int) {

        }
    }

    /** 交易链路回调 */
    val tradeSocketListener = object : MTP2SocketListener<Packet50> {
        override fun onConnected(socket: MTP2Socket<Packet50>?) {

        }

        override fun onClosed(socket: MTP2Socket<Packet50>?) {

        }

        override fun onError(socket: MTP2Socket<Packet50>?, err: Error?) {

        }

        override fun onReceivePush(socket: MTP2Socket<Packet50>?, data: Packet50?) {
            when (data?.funCode) {
                FunCode.LogoutRsp -> { // 用户登出通知，多点登录下发
                    //登出弹窗
                    showDialog()
                }
                FunCode.CustOfflineNtf -> { // 用户离线通知，交易接入异常时下发
                    // TODO: - 加登出提示
                    exitApp()
                }
            }
        }

        override fun onReconnectChangeState(socket: MTP2Socket<Packet50>?, state: Int) {
            LogUtils.eTag("RAM_RC", "++++++++++++++ Reconnecting ++++++++++++++")
            LogUtils.eTag("RAM_RC", String.format("交易链路断网重连状态变更：%d", state))

            when (state) {
                MTP2Socket.ReconnectChangeState_BeginReconnect -> { // 开始断网重连
                    // 停止心跳
                    socket?.stopBeatTimer()
                    // 如果是交易连路则停止定时Token检验
                    if (socket?.packetType == 1) {
                        accountManager?.stopTokenCheckTimer()
                    }
                }
                MTP2Socket.ReconnectChangeState_ReconnectSuccessed -> { // 重连成功，将进行业务操作
                    // 进行断网重连Token检验
                    accountManager?.tokenCheckAndLoginByReconnected()
                }
                MTP2Socket.ReconnectChangeState_LoginFail -> {  // 重连成功后业务操作失败，由业务模块发起
                    // 退出应用，并显示登录界面
                    exitApp()
                }
                MTP2Socket.ReconnectChangeState_Logined -> { // 重连成功后业务操作成功（包括交易服务的账户登录状态更新或行情服务的行情订阅等）
                    // 开始心跳
                    socket?.startBeatTime()
                    // 开始定时Token检验
                    accountManager?.startTokenCheckTimer()
                }
            }
        }

    }

    /**
     * 获取当前显示activity的context
     */
    private fun initLifecycle() {
        registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
            override fun onActivityPaused(p0: Activity) {

            }

            override fun onActivityStarted(activity: Activity) {
                context = if (activity.parent != null) {//如果这个视图是嵌入的子视图
                    activity.parent
                } else {
                    activity;
                }
            }

            override fun onActivityDestroyed(p0: Activity) {

            }

            override fun onActivitySaveInstanceState(p0: Activity, p1: Bundle) {

            }

            override fun onActivityStopped(p0: Activity) {

            }

            override fun onActivityCreated(activity: Activity, p1: Bundle?) {
                context = if (activity.parent != null) {//如果这个视图是嵌入的子视图
                    activity.parent
                } else {
                    activity;
                }
            }

            override fun onActivityResumed(activity: Activity) {
                context = if (activity.parent != null) {//如果这个视图是嵌入的子视图
                    activity.parent
                } else {
                    activity;
                }
            }
        })
    }

    /**
     * 登出弹窗
     */
    private fun showDialog() {
        Thread(Runnable {
            Looper.prepare()//
            val builder  = AlertDialog.Builder(context)
            builder.setTitle("温馨提示")
            builder.setMessage("您的账号在别处登陆")
                .setCancelable(false)
            builder.setPositiveButton("确定"
            ) { _, _ -> exitApp() }
            val alert: AlertDialog = builder.create()
            alert.setCancelable(false)
            alert.show()
            Looper.loop()
        }).start()
    }
}