package com.quyunshuo.module.home.service

import ZtlApi.ZtlManager
import android.annotation.SuppressLint
import android.app.AlarmManager
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Build
import android.os.IBinder
import android.util.Log
import android.view.WindowManager
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.hboxs.serialport.plc.DialogClickListener
import com.hboxs.serialport.sbc.VBoxMessage
import com.hboxs.serialport.sbc.VboxSerialPortDevice
import com.hboxs.serialport.sbc.VboxSerialPortManager
import com.hjq.http.lifecycle.LifecycleService
import com.module.database.room.SZDatabase
import com.module.pay.common.PayAgreementUtil
import com.module.pay.nayax.CreditCardPresenter
import com.module.pay.service.HomeApiService
import com.module.pay.strategy.PaySendDataFactory
import com.quyunshuo.androidbaseframemvvm.base.BaseApplication
import com.quyunshuo.androidbaseframemvvm.base.addressenum.PayEnum
import com.quyunshuo.androidbaseframemvvm.base.ktx.observeLiveData
import com.quyunshuo.androidbaseframemvvm.base.utils.SpUtils
import com.quyunshuo.androidbaseframemvvm.common.bean.PayTypeBean
import com.quyunshuo.androidbaseframemvvm.common.constant.MMKVName
import com.quyunshuo.androidbaseframemvvm.common.constant.MqName
import com.quyunshuo.androidbaseframemvvm.common.constant.event.ApiMessageEvent
import com.quyunshuo.androidbaseframemvvm.common.enums.AlarmClockEnum
import com.quyunshuo.androidbaseframemvvm.common.util.AlarmManagerUtil.ALARM_ACTION
import com.quyunshuo.androidbaseframemvvm.common.util.ToastUtil
import com.quyunshuo.androidbaseframemvvm.common.util.UiUtil
import com.quyunshuo.androidbaseframemvvm.common.util.XLogUtil
import com.quyunshuo.module.home.R
import com.quyunshuo.module.home.dialog.CountDownDialogFragment
import com.quyunshuo.module.home.dialog.ErrorDialog
import com.quyunshuo.module.home.dialog.LoadingDialog
import com.quyunshuo.module.home.dialog.OpenOrCloseDialog
import com.quyunshuo.module.home.dialog.WarringDialog
import com.quyunshuo.module.home.receiver.TimedCleaningTaskAlarmReceiver
import com.quyunshuo.module.home.utils.UploadWorker
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import javax.inject.Inject


/**
 * 全局service：作为全局读取d2的一个服务
 */
@AndroidEntryPoint
class GlobalService : LifecycleService() {
    private val TAG = "GlobalService"

    @Inject
    lateinit var globalServiceViewModel: GlobalServiceViewModel
    private var sbcInitDialog: CountDownDialogFragment? = null//通电初始化
    private var warringDialog: WarringDialog? = null//报警对话框
    private val NOTIFICATION_ID = "1"
    private val NOTIFICATION_NAME: CharSequence = "GlobalService"
    var errorDialog: ErrorDialog? = null
    var openOrClose: OpenOrCloseDialog? = null
    var loadingDialog: LoadingDialog? = null
    private val localOrderDao = SZDatabase.getDatabase(BaseApplication.context).getLocalOrderDao()

    @Inject
    lateinit var mApi: HomeApiService

    //  val warringDao = SZDatabase.getDatabase(BaseApplication.context).getWarringDao()
    //这个必须加，不能设置为null
    private fun getNotification(): Notification {
        val builder: Notification.Builder = Notification.Builder(this)
            .setContentTitle("GlobalService")
            .setContentText("我正在运行") //标题和内容可以不加
        //设置Notification的ChannelID,否则不能正常显示
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            builder.setChannelId(NOTIFICATION_ID)
        }
        val notification = builder.build()
        return notification
    }

    var alarmReceiver: TimedCleaningTaskAlarmReceiver? = null

    @SuppressLint("ForegroundServiceType")
    override fun onCreate() {
        super.onCreate()
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            alarmReceiver = TimedCleaningTaskAlarmReceiver()
            val filter = IntentFilter(ALARM_ACTION)
            registerReceiver(alarmReceiver, filter)
        }

        UploadWorker.getInstance().init(this, localOrderDao, api = mApi)
        //初始化plc
        connectDevice()
        val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager

        //创建NotificationChannel
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(
                NOTIFICATION_ID,
                NOTIFICATION_NAME,
                NotificationManager.IMPORTANCE_HIGH
            )
            notificationManager.createNotificationChannel(channel)
            startForeground(1, getNotification())
        }
        EventBus.getDefault().register(this)
//        globalServiceViewModel.getVideoRule()
        globalServiceViewModel.getAlarmClock()
//        globalServiceViewModel.scheduleDailyAlarmWithWorkManager(this@GlobalService);
        //初始化 支付的串口通讯
        initPayIctMdb()
        showTipsDialog(UiUtil.getStringRes(com.quyunshuo.androidbaseframemvvm.base.R.string.base_init))
        observeLiveData(globalServiceViewModel.initIsSuccess, ::initIsSuccess)
        observeLiveData(globalServiceViewModel.closeError, ::closeErrorDialog)
        observeLiveData(globalServiceViewModel.error, ::showErrorDialog)
        observeLiveData(globalServiceViewModel.showOrCloseLoading, ::showOrCloseLoading)
        observeLiveData(globalServiceViewModel.showStartupOrShutdown, ::showStartOrShutdown)
        observeLiveData(globalServiceViewModel.finshStartupOrShutdown, ::CloseStartOrShutdown)

        observeLiveData(globalServiceViewModel.aginstartInit, ::aginInit)
        //开启自启热点设置
        if (SpUtils.getBoolean(MMKVName.AUTO_START_HOTSPOT, false) == true) {
            ZtlManager.GetInstance().openAp(
                SpUtils.getString(
                    MMKVName.NAME_HOTSPOT,
                    "sunzee"
                ), SpUtils.getString(MMKVName.PWD_HOTSPOT, "66666666")
            );
        }
        globalServiceViewModel.aMap()
        globalServiceViewModel.forceBackToApp()
    }

    fun aginInit(init: Boolean) {

        restartApp(this, true)
    }

    fun restartApp(context: Context, killProcess: Boolean = true) {
        val intent = context.packageManager.getLaunchIntentForPackage(context.packageName)?.apply {
            addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
        }
        context.startActivity(intent)

        if (killProcess) {
            (context.getSystemService(Context.ALARM_SERVICE) as AlarmManager).apply {
                set(
                    AlarmManager.RTC, System.currentTimeMillis() + 500,
                    PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
                )
            }
            android.os.Process.killProcess(android.os.Process.myPid())
        }
    }

    private fun connectDevice() {

        //对单片机进行连接
        val device: VboxSerialPortDevice =
            VboxSerialPortDevice("dev/" + SpUtils.getString(MMKVName.TTYS_PLC, "ttyS7"), "115200")
        try {
            VboxSerialPortManager.getInstance().open(device)
        } catch (e: Exception) {
            Log.d(TAG, "connectDevice 串口打开失败: ")
        }
        Log.d(TAG, "connectDevice 串口打开成功: ")
    }

    private fun initIsSuccess(initIsSuccess: Boolean) {
        //是否初始化成功，如果成功，提前结束，如果失败，什么都不做。
        if (initIsSuccess) {
            sbcInitDialog?.dismiss()
            ToastUtil.switchToastStyleToSuccess("通电初始化成功。")
            globalServiceViewModel.threadGlobalParam.stopInit()
            //初始化成功，则可以开始读取心跳了。
            globalServiceViewModel.startHeartbeat()

//            globalServiceViewModel.sendBackData()
            XLogUtil.d("sendBackData 开始了")

        }
    }


    private fun closeErrorDialog(closeError: Boolean) {
        //是否初始化成功，如果成功，提前结束，如果失败，什么都不做。
        if (errorDialog != null && errorDialog?.isShowing == true) {
            errorDialog?.dismiss()
        }
    }

    var arrayListState: HashMap<String, PayTypeBean> = HashMap()

    private fun initPayIctMdb() {
        val productStr = SpUtils.getString(MMKVName.PAY_TYPE, "")
        if (productStr != "") {
            arrayListState = Gson().fromJson(
                productStr,
                object : TypeToken<HashMap<String, PayTypeBean>?>() {}.type
            )
        }
        if (arrayListState != null) {
            var nayax = arrayListState[PayEnum.NAYAX.code]
            var mdb = arrayListState[PayEnum.MDB_NO_CASH.code]
            var bill = arrayListState[PayEnum.BILL_COIN.code]
            CoroutineScope(Dispatchers.IO).launch {
                //MDB ICT
                if (mdb != null || bill != null) {
                    val payAgreement = SpUtils.getInt(MMKVName.MDB, 0)
                    XLogUtil.d("initPayIctMdb ：" + PayAgreementUtil.MDB_ICT[payAgreement!!])
                    val createStrategy =
                        PaySendDataFactory.createStrategy(PayAgreementUtil.MDB_ICT[payAgreement!!])
                    createStrategy.billInit()
                    delay(2000)//休眠两秒，间隔一下。
                    createStrategy.initCreditCard()
                    launch {
                        while (true) {
                            delay(10000)
                            createStrategy.creditPoll()
                        }
                    }
                }

                if (nayax != null) {
                    //Nayax 初始化
                    CreditCardPresenter.getCreditCardContract()
                }

            }
        }


    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun event(message: ApiMessageEvent) {
        when (message.name) {
            MqName.PUSHTIMERULE -> {
                globalServiceViewModel.getVideoRule(message.data as String)

            }

            AlarmClockEnum.OPEN_DEV.code -> {
                globalServiceViewModel.openOrClose("01")
            }

            AlarmClockEnum.CLOSE_DEV.code -> {
                globalServiceViewModel.openOrClose("00")
            }

            AlarmClockEnum.CLOSE_DEV.code + "show" -> {

            }


        }
    }


    @Subscribe(threadMode = ThreadMode.MAIN)
    fun event(messageEvent: VBoxMessage) {
        XLogUtil.d("VBoxMessage:$messageEvent")
        globalServiceViewModel.disposeData(messageEvent)
    }

    override fun onDestroy() {
        super.onDestroy()
        EventBus.getDefault().unregister(this)
        alarmReceiver?.let { unregisterReceiver(it) }

    }

    override fun onBind(intent: Intent?): IBinder? {
        return null
    }

    private fun showOrCloseLoading(isShow: Boolean) {
        if (loadingDialog == null) {
            loadingDialog = this@GlobalService.baseContext?.let { LoadingDialog(it) }
        }
        loadingDialog?.setCancelable(false)
        if (Build.VERSION.SDK_INT >= 26) {
            loadingDialog?.window?.setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY)
        } else {
            loadingDialog?.window?.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)
        }
        if (isShow) {
            loadingDialog?.show()
            loadingDialog?.startCustomRotation()
        } else {
            loadingDialog?.stopCustomRotation()
            loadingDialog?.dismiss()
        }


    }

    private fun CloseStartOrShutdown(dismiss: Boolean) {
        openOrClose?.dismiss()
    }


    private fun showStartOrShutdown(isStartup: Boolean) {
        if (openOrClose == null) {
            openOrClose = this@GlobalService.baseContext?.let { OpenOrCloseDialog(it) }
        }
        if (isStartup) {
            openOrClose?.setContent(getString(R.string.base_startup))
        } else {
            openOrClose?.setContent(getString(R.string.base_shutdown))

        }
        openOrClose?.setCancelable(false)
        if (Build.VERSION.SDK_INT >= 26) {
            openOrClose?.window?.setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY)
        } else {
            openOrClose?.window?.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)
        }
        if (openOrClose?.isShowing == false) {
            openOrClose?.show()
        }


    }

    private fun showErrorDialog(type: String) {
        if (errorDialog == null) {
            errorDialog = this@GlobalService.baseContext?.let { ErrorDialog(it) }
        }
        if (errorDialog?.isShowing == false) {
            errorDialog?.setType(type)
            errorDialog?.setListener(object : DialogClickListener {
                override fun onClickListener(type: Int, text: String?) {
                    when (type) {
                        errorDialog?.type1 -> {
                            ToastUtil.switchToastStyleToWarn("关闭致命报警")
                            globalServiceViewModel.startCloseError(true)

                        }

                        errorDialog?.type2 -> {
                            ToastUtil.switchToastStyleToWarn("关闭非致命报警")
                            globalServiceViewModel.startCloseError(false)

                        }

                        else -> {}
                    }
                }
            })
            errorDialog?.setCancelable(false)
            if (Build.VERSION.SDK_INT >= 26) {
                errorDialog?.window?.setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY)
            } else {
                errorDialog?.window?.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)
            }
            errorDialog?.show()
        }


    }


    /**
     * 通电初始化 弹窗提醒
     */
    private fun showTipsDialog(content: String) {
        if (sbcInitDialog == null) {
            sbcInitDialog = this@GlobalService.baseContext?.let { CountDownDialogFragment(it) }
        }
        sbcInitDialog?.setListener(object : DialogClickListener {
            override fun onClickListener(type: Int, text: String?) {
                when (type) {
                    sbcInitDialog?.type1 -> {
                        sbcInitDialog?.dismiss()
                        globalServiceViewModel.threadGlobalParam.stopInit()
                        //判断初始化失败
                        ToastUtil.switchToastStyleToError("通电初始化失败。")
                        showWarringDialog(UiUtil.getStringRes(com.quyunshuo.androidbaseframemvvm.base.R.string.base_init_fail))
                    }

                    else -> {}
                }
            }
        })
        if (Build.VERSION.SDK_INT >= 26) {
            sbcInitDialog?.window?.setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY)
        } else {
            sbcInitDialog?.window?.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)
        }
        sbcInitDialog?.setCanceledOnTouchOutside(false)
        sbcInitDialog?.setContent(content)
        sbcInitDialog?.show()
        globalServiceViewModel.threadGlobalParam.startInit()
    }

    /**
     * 报警 弹窗提醒
     */
    private fun showWarringDialog(content: String) {
        if (warringDialog == null) {
            warringDialog = this@GlobalService.baseContext?.let { WarringDialog(it) }
        }
        warringDialog?.setListener(object : DialogClickListener {
            override fun onClickListener(type: Int, text: String?) {
                when (type) {
                    warringDialog?.type1 -> {
                        warringDialog?.dismiss()
                    }

                    else -> {}
                }
            }
        })
        if (Build.VERSION.SDK_INT >= 26) {
            warringDialog?.window?.setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY)
        } else {
            warringDialog?.window?.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)
        }
        warringDialog?.setCanceledOnTouchOutside(false)
        warringDialog?.setContent(content)

        warringDialog?.show()
        globalServiceViewModel.threadGlobalParam.startInit()
    }


}