package com.gh.common.simulator

import android.app.Dialog
import android.content.Context
import android.view.View
import android.view.Window
import android.widget.ProgressBar
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintLayout
import com.gh.common.util.LogUtils
import com.gh.common.util.NewFlatLogUtils
import com.gh.common.util.PackageInstaller
import com.gh.common.util.PackageUtils
import com.gh.download.DownloadManager
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.TrackableDialog
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.AppExecutor.uiExecutor
import com.gh.gamecenter.core.utils.*
import com.gh.gamecenter.feature.entity.ApkEntity
import com.gh.gamecenter.feature.entity.SimulatorEntity
import com.gh.gamecenter.entity.TrackableEntity
import com.gh.ndownload.NDataChanger
import com.halo.assistant.HaloApp
import com.lightgame.download.DataWatcher
import com.lightgame.download.DownloadEntity
import com.lightgame.download.DownloadStatus
import com.lightgame.download.FileUtils
import com.lightgame.utils.Utils
import java.lang.ref.WeakReference
import java.text.DecimalFormat

class SimulatorDownloadManager private constructor() {

    private var app_pb_progress: ProgressBar? = null
    private var appProgressSize: TextView? = null
    private var appProgressRemain: TextView? = null
    private var appProgressPercent: TextView? = null
    private var appProgressFilling: View? = null
    private var appProgressAnchor: View? = null
    private var downloadDialog: Dialog? = null
    private var mContextRef: WeakReference<Context>? = null

    private var simulatorLocation: SimulatorLocation? = null
    private var simulator: SimulatorEntity? = null
    private var gameId: String = ""
    private var gameName: String = ""
    private var downloadType: String = ""

    private val dataWatcher = object : DataWatcher() {
        override fun onDataChanged(downloadEntity: DownloadEntity?) {
            if (downloadEntity?.isSimulatorDownload() == true) {
                val size = downloadEntity.progress.toFloat() / 1024 / 1024
                val df = DecimalFormat("0.00")
                appProgressSize!!.text = "${df.format(size.toDouble())}MB"
                appProgressRemain!!.text = String.format(
                    "剩余%s", SpeedUtils.getRemainSecondTime(
                        downloadEntity.size,
                        downloadEntity.progress, downloadEntity.speed * 1024
                    )
                )
                app_pb_progress!!.progress = (downloadEntity.percent * 10).toInt()

                val width = app_pb_progress!!.width
                val marLeft = (downloadEntity.percent / 100 * width).toInt()
                val anchorLp = appProgressAnchor!!.layoutParams
                if (anchorLp is ConstraintLayout.LayoutParams) {
                    anchorLp.leftMargin = marLeft
                    appProgressAnchor!!.layoutParams = anchorLp
                }

                val fillingLp = appProgressFilling!!.layoutParams
                fillingLp.width = marLeft + DisplayUtils.dip2px(5f)
                appProgressFilling!!.layoutParams = fillingLp

                appProgressPercent?.text = if (downloadEntity.percent != 100.0) "${downloadEntity.percent}%" else "100%"
                when {
                    DownloadStatus.done == downloadEntity.status -> {
                        val locationStr =
                            if (simulatorLocation == SimulatorLocation.LAUNCH) "${simulatorLocation?.value}《${gameName}》" else simulatorLocation?.value
                        val fileName =
                            downloadEntity.path.substring(downloadEntity.path.lastIndexOf('/') + 1).removeSuffix(".apk")
                        val startTime = downloadEntity.getMetaExtra(Constants.SIMULATOR_DOWNLOAD_START_TIME)
                        LogUtils.uploadSimulatorDownload(
                            "simulator_download_complete",
                            fileName,
                            simulator?.id,
                            downloadEntity.name,
                            gameId,
                            locationStr,
                            downloadType,
                            startTime
                        )
                        DownloadManager.getInstance().cancel(downloadEntity.url, false, true, false)
                        val activity = mContextRef?.get() as? AppCompatActivity
                        if (activity?.isFinishing == false) {
                            downloadDialog?.dismiss()
                        }
                    }
                    DownloadStatus.diskisfull == downloadEntity.status -> {
                        ToastUtils.showToast("存储空间已满，下载任务已暂停")
                    }
                    DownloadStatus.diskioerror == downloadEntity.status -> {
                        ToastUtils.showToast("下载 IO 出现异常，下载任务已暂停")
                    }
                    DownloadStatus.neterror == downloadEntity.status -> {
                        ToastUtils.showToast("网络不稳定，下载任务已暂停")
                    }
                    DownloadStatus.timeout == downloadEntity.status -> {
                        ToastUtils.showToast("网络不稳定，下载任务已暂停")
                    }
                    DownloadStatus.notfound == downloadEntity.status -> {
                        ToastUtils.showToast("下载链接异常，请稍后重试")
                    }
                    DownloadStatus.uncertificated == downloadEntity.status -> {
                        ToastUtils.showToast("请先进行实名认证")
                    }
                    DownloadStatus.unqualified == downloadEntity.status -> {
                        ToastUtils.showToast("未成年人暂不允许在此时间下载游戏")
                    }
                    DownloadStatus.unavailable == downloadEntity.status -> {
                        ToastUtils.showToast("该游戏未接入防沉迷系统，暂不支持下载")
                    }
                    DownloadStatus.banned == downloadEntity.status -> {
                        ToastUtils.showToast("网络异常")
                    }
                    DownloadStatus.hijack == downloadEntity.status -> {
                        ToastUtils.showToast("网络劫持，请稍后重试")
                    }
                }
            }
        }
    }

    fun showDownloadDialog(context: Context, simulator: SimulatorEntity?, location: SimulatorLocation) {
        showDownloadDialog(context, simulator, location, "", "", null)
    }

    fun showDownloadDialog(
        context: Context?,
        simulator: SimulatorEntity?,
        location: SimulatorLocation,
        gameId: String = "",
        gameName: String = "",
        cancelCallback: (() -> Unit)? = null
    ) {
        if (context == null) return

        this.simulatorLocation = location
        this.simulator = simulator
        this.gameId = gameId
        this.gameName = gameName

        PermissionHelper.checkGetInstalledAppsListBeforeAction(context, object : EmptyCallback {
            override fun onCallback() {
                val isInstalledNewSimulator =
                    SimulatorGameManager.isNewSimulatorInstalled(HaloApp.getInstance().application)
                //当没有安装新版本模拟器时候 判断是否隐藏
                if (simulator?.active == false && !isInstalledNewSimulator) {
                    showNoneEmulatorDialog(context)
                    return
                }
                var isInstalled = PackageUtils.isInstalledFromAllPackage(
                    context,
                    simulator?.apk?.packageName
                )
                //模拟器管理界面还是用之前的逻辑
                if (isInstalledNewSimulator && location != SimulatorLocation.SIMULATOR_MANAGE) {
                    isInstalled = isInstalledNewSimulator
                }
//                val versionFromInstalledApp = PackageUtils.getVersionNameByPackageName(simulator?.apk?.packageName)
                val shouldShowUpdate =
                    PackageUtils.isInstalledApkMatchedMd5(simulator?.apk?.packageName, simulator?.apk?.md5)
                val showAlertTag = SPUtils.getString(SimulatorGameManager.SIMULATOR_UPDATE_SHOW_ALERT_TAG, "") //当天是否弹过
                val todayIsShow = showAlertTag == TimeUtils.getToday()
                downloadType = if (shouldShowUpdate && isInstalled) "update" else "download"
                if (downloadType == "update" && todayIsShow && location != SimulatorLocation.SIMULATOR_MANAGE) {
                    return
                }
                if (downloadType == "download" && isInstalled) {
                    return
                }
                val title = if (shouldShowUpdate && isInstalled) "更新模拟器" else "安装模拟器"
                val message = if (shouldShowUpdate && isInstalled) "检测到模拟器存在更高版本，是否前往更新" else "模拟器游戏需要先下载安装对应的模拟器，才可以运行"
                val positiveText =
                    if (shouldShowUpdate && isInstalled) "更新（${simulator?.apk?.size}）" else "下载（${simulator?.apk?.size}）"
                val negativeText = if (shouldShowUpdate && isInstalled) "下次再说" else "取消"
                val trackableEntity = TrackableEntity(
                    "模拟器下载",
                    key = if (shouldShowUpdate && isInstalled) "更新弹窗" else "下载弹窗",
                    logShowEvent = true
                )
                if (shouldShowUpdate && isInstalled) {
                    NewFlatLogUtils.logSimulatorUpdateAlertShow()
                }
                DialogHelper.showDialog(
                    context,
                    title,
                    message,
                    positiveText,
                    negativeText,
                    trackMtaEvent = true,
                    cancelClickCallback = {
                        if (shouldShowUpdate && isInstalled) {
                            cancelCallback?.invoke()
                            NewFlatLogUtils.logSimulatorUpdateAlertClick("取消")
                            MtaHelper.onEvent(trackableEntity.event, trackableEntity.key, "点击下次再说")
                        }
                    },
                    confirmClickCallback = {
                        showDownloadingDialog(context, simulator)
                        NewFlatLogUtils.logSimulatorUpdateAlertClick("更新")
                        MtaHelper.onEvent(
                            trackableEntity.event,
                            trackableEntity.key,
                            if (shouldShowUpdate && isInstalled) "点击更新" else "点击下载"
                        )
                    },
                    mtaEvent = trackableEntity.event, mtaKey = trackableEntity.key,
                    extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true)
                )
                if (downloadType == "update" && location != SimulatorLocation.SIMULATOR_MANAGE) {
                    SPUtils.setString(SimulatorGameManager.SIMULATOR_UPDATE_SHOW_ALERT_TAG, TimeUtils.getToday())
                }
            }
        })
    }

    fun showDownloadingDialog(context: Context, simulator: SimulatorEntity?) {
        mContextRef = WeakReference(context)
        val msg = FileUtils.isCanDownload(context, simulator?.apk?.size)
        if (!msg.isNullOrEmpty()) {
            Utils.toast(context, msg)
            return
        }
        if (NetworkUtils.isMobileConnected(context)) {
            Utils.toast(context, "当前使用移动数据进行下载")
        }

        downloadDialog = TrackableDialog(context, R.style.GhAlertDialog, "模拟器下载", "下载中弹窗")
        downloadDialog?.window?.setBackgroundDrawableResource(R.color.transparent)

        val view = View.inflate(context, R.layout.download_simulator_dialog, null)

        app_pb_progress = view.findViewById(R.id.progress)
        appProgressSize = view.findViewById(R.id.size)
        appProgressRemain = view.findViewById(R.id.remain)
        appProgressAnchor = view.findViewById(R.id.progress_anchor)
        appProgressPercent = view.findViewById(R.id.percent)
        appProgressFilling = view.findViewById(R.id.progress_filling)

        view.findViewById<View>(R.id.app_tv_cancel).setOnClickListener {
            DownloadManager.getInstance().pause(simulator?.apk?.url)
            MtaHelper.onEvent("模拟器下载", "下载中弹窗", "点击关闭")
            val activity = mContextRef?.get() as? AppCompatActivity
            if (activity?.isFinishing == false) {
                downloadDialog?.dismiss()
            }
        }

        downloadDialog?.setOnDismissListener {
            DownloadManager.getInstance().removeObserver(dataWatcher)
        }

        downloadDialog?.setCanceledOnTouchOutside(false)
        downloadDialog?.setCancelable(false)
        downloadDialog?.closeOptionsMenu()
        downloadDialog?.requestWindowFeature(Window.FEATURE_NO_TITLE)
        downloadDialog?.setContentView(view)
        val params = downloadDialog?.window?.attributes
        params?.width = context.resources.displayMetrics.widthPixels - DisplayUtils.dip2px(60f)
        downloadDialog?.window?.attributes = params

        download(simulator)
    }

    private fun showNoneEmulatorDialog(context: Context) {
        DialogHelper.showDialog(
            context,
            "安装模拟器",
            "模拟器游戏需要先下载安装对应的模拟器，才可以运行",
            "暂无下载",
            "取消",
            confirmClickCallback = {
                ToastUtils.showToast("该模拟器暂未提供下载")
            },
            uiModificationCallback = { binding ->
                binding.confirmTv.setTextColor(R.color.text_body.toColor(context))
            },
            extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true)
        )
    }

    private fun download(simulator: SimulatorEntity?) {
        val apkEntity = simulator?.apk ?: return

        val entity = DownloadManager.getInstance().getDownloadEntityByUrl(apkEntity.url)
        HaloApp.put(simulator.name, simulator)
        if (entity != null) {
            when (entity.status) {
                DownloadStatus.pause,
                DownloadStatus.subscribe,
                DownloadStatus.neterror,
                DownloadStatus.timeout,
                DownloadStatus.diskioerror,
                DownloadStatus.diskisfull -> {
                    DownloadManager.getInstance().addObserver(dataWatcher)
                    uiExecutor.executeWithDelay(Runnable { DownloadManager.getInstance().resume(entity, true) }, 200)
                    downloadDialog?.show()
                }
                DownloadStatus.done -> NDataChanger.notifyDataChanged(entity)

                else -> createDownload(apkEntity, simulator)
            }
        } else {
            createDownload(apkEntity, simulator)
        }
    }

    private fun createDownload(apkEntity: ApkEntity, simulator: SimulatorEntity) {
        DownloadManager.getInstance().addObserver(dataWatcher)
        val downloadId = PackageInstaller.createDownloadId(simulator.name)
        val downloadEntity = DownloadEntity()
        downloadEntity.url = apkEntity.url
        downloadEntity.name = simulator.name
        downloadEntity.path = PackageInstaller.getDownloadPathWithId(downloadId, apkEntity.format)
        downloadEntity.platform = apkEntity.getPlatform()
        downloadEntity.packageName = apkEntity.packageName
        downloadEntity.versionName = apkEntity.version

        downloadEntity.addMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE, Constants.SIMULATOR_DOWNLOAD)
        downloadEntity.addMetaExtra(
            Constants.SIMULATOR_DOWNLOAD_START_TIME,
            (System.currentTimeMillis() / 1000).toString()
        )
        downloadEntity.addMetaExtra(Constants.DOWNLOAD_ID, downloadId)
        uiExecutor.executeWithDelay(Runnable { DownloadManager.getInstance().add(downloadEntity) }, 200)

        val locationStr =
            if (simulatorLocation == SimulatorLocation.LAUNCH) "${simulatorLocation?.value}《${gameName}》" else simulatorLocation?.value
        val fileName = downloadEntity.path.substring(downloadEntity.path.lastIndexOf('/') + 1).removeSuffix(".apk")
        LogUtils.uploadSimulatorDownload(
            "simulator_download",
            fileName,
            simulator.id,
            simulator.name,
            gameId,
            locationStr,
            downloadType,
            ""
        )

        downloadDialog?.show()
    }


    companion object {
        @Volatile
        private var instance: SimulatorDownloadManager? = null

        @JvmStatic
        fun getInstance(): SimulatorDownloadManager {
            return instance ?: synchronized(this) {
                instance ?: SimulatorDownloadManager().also { instance = it }
            }
        }

    }

    enum class SimulatorLocation(val value: String) {
        LAUNCH("启动"),
        SIMULATOR_GAME("模拟器游戏"),
        SIMULATOR_MANAGE("模拟器游戏-模拟器管理")
    }
}