package com.gh.gamecenter.fragment

import android.annotation.SuppressLint
import android.app.Dialog
import android.content.Context
import android.content.DialogInterface
import android.os.Bundle
import android.text.Html
import android.text.TextUtils
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout
import com.gh.common.util.DirectUtils
import com.gh.common.util.PackageInstaller
import com.gh.download.DownloadManager
import com.gh.gamecenter.common.base.fragment.BaseDialogFragment
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.view.CustomLinkMovementMethod
import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.core.utils.*
import com.gh.gamecenter.databinding.AppUpdateHintDialogBinding
import com.gh.gamecenter.databinding.AppUpdatingDialogBinding
import com.gh.gamecenter.databinding.DialogUpdateBinding
import com.gh.gamecenter.entity.AppEntity
import com.gh.gamecenter.update.UpdateHelper
import com.lightgame.download.DataWatcher
import com.lightgame.download.DownloadEntity
import com.lightgame.download.DownloadStatus
import java.text.DecimalFormat
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.math.roundToInt

/**
 * 更新弹窗 DialogFragment
 */
class UpdateDialogFragment : BaseDialogFragment() {

    private var mUpdateEntity: AppEntity? = null
    private var mDismissCallback: EmptyCallback? = null
    private val mIsDismissByTouchInside = AtomicBoolean(false)
    private val mBinding by lazy { DialogUpdateBinding.inflate(layoutInflater) }

    private var mIsDisplayingDownloadingStyle = false // 是否正在显示更新中样式

    private val mDataWatcher = object : DataWatcher() {
        override fun onDataInit(downloadEntity: DownloadEntity) {
            super.onDataInit(downloadEntity)

            onDataChanged(downloadEntity)
        }

        override fun onDataChanged(downloadEntity: DownloadEntity) {
            if (downloadEntity.name.contains("光环助手")) {
                if (mIsDisplayingDownloadingStyle) {
                    updateDownloadingView(
                        mBinding.updatingContainerView,
                        downloadEntity,
                        mUpdateEntity!!
                    )
                } else {
                    if (DownloadStatus.done == downloadEntity.status) {
                        updateUpdateHintView(
                            mBinding.updateHintContainerView,
                            mUpdateEntity!!,
                            UpdateHelper.isUpdateFileDownloaded(mUpdateEntity!!)
                        )
                    }
                }
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        if (savedInstanceState != null) {
            dismiss()
            return
        }

        mUpdateEntity = arguments?.getParcelable(UPDATE_ENTITY)
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
        showUpdateHintStyle(requireContext(), mUpdateEntity!!, true)

        return mBinding.root
    }

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        return super.onCreateDialog(savedInstanceState).apply {
            val cancelable = !mUpdateEntity!!.isForce

            setCancelable(cancelable)
            setCanceledOnTouchOutside(cancelable)
            this@UpdateDialogFragment.isCancelable = cancelable
        }
    }

    override fun onDismiss(dialog: DialogInterface) {
        super.onDismiss(dialog)

        if (!mIsDismissByTouchInside.get()) {
            SensorsBridge.trackVersionUpdateDialogClick(
                buttonName = "关闭弹窗",
                keyDialogReminderTime = mUpdateEntity?.alert,
                keyDialogClose = if (mUpdateEntity?.isForce == true) "关闭且强退" else "仅关闭"
            )
        }

        mDismissCallback?.onCallback()
    }

    override fun onStart() {
        super.onStart()

        DownloadManager.getInstance().addObserver(mDataWatcher)
    }

    override fun onStop() {
        super.onStop()

        DownloadManager.getInstance().removeObserver(mDataWatcher)
    }

    /**
     * 显示更新弹窗（提示样式）
     * @param context 上下文
     * @param updateEntity 更新实体
     */
    private fun showUpdateHintStyle(context: Context,
                                    updateEntity: AppEntity,
                                    invokeByViewCreated: Boolean) {
        mIsDisplayingDownloadingStyle = false

        val updateHintBinding = mBinding.updateHintContainerView
        val updatingBinding = mBinding.updatingContainerView

        updatingBinding.root.visibility = View.GONE
        updateHintBinding.root.visibility = View.VISIBLE

        val cancelUpdateTextView = updateHintBinding.cancel
        val confirmTextView = updateHintBinding.confirm

        if (!TextUtils.isEmpty(updateEntity.spareLink)) {
            val defaultText = "部分设备若无法更新安装，请前往官网进行下载安装："
            val externalTextTv = updateHintBinding.externalTextTv
            val builder = SpanBuilder(defaultText + updateEntity.spareLink)
                .click(
                    context,
                    defaultText.length,
                    defaultText.length + updateEntity.spareLink!!.length,
                    com.gh.gamecenter.common.R.color.text_theme,
                    false
                ) {
                    DirectUtils.directToExternalBrowser(context, updateEntity.spareLink!!)
                }
                .build()
            externalTextTv.text = builder
            externalTextTv.movementMethod = CustomLinkMovementMethod.getInstance()
            externalTextTv.visibility = View.VISIBLE
        }

        val updateFileIsDownloaded = UpdateHelper.isUpdateFileDownloaded(updateEntity)

        if (NetworkUtils.isWifiConnected(context)) {
            if (!updateFileIsDownloaded) {
                updateUpdateHintView(updateHintBinding, updateEntity, false)
                UpdateHelper.createUpdate(updateEntity, true)
            } else {
                updateUpdateHintView(updateHintBinding, updateEntity, true)
            }
        } else {
            updateUpdateHintView(updateHintBinding, updateEntity, updateFileIsDownloaded)
        }

        updateHintBinding.desc.text = Html.fromHtml(updateEntity.content)
        updateHintBinding.version.text = java.lang.String.format("版本%s更新日志：", updateEntity.version)
        updateHintBinding.size.text = java.lang.String.format("大小 %s", updateEntity.size)

        cancelUpdateTextView.setOnClickListener {
            val cancelText: String = cancelUpdateTextView.text.toString()
            SensorsBridge.trackVersionUpdateDialogClick(
                buttonName = cancelText,
                keyDialogReminderTime = mUpdateEntity?.alert,
                keyDialogClose = if (mUpdateEntity?.isForce == true) "关闭且强退" else "仅关闭"
            )
            mIsDismissByTouchInside.set(true)
            if (updateEntity.isForce) {
                AppExecutor.uiExecutor.executeWithDelay({ UpdateHelper.exitApp() }, 500L)
            } else {
                dismiss()
            }
        }

        confirmTextView.setOnClickListener {
            // 产品不接受显示下载完成文案从立即更新变为立即安装，所以文案为立即更新时一律不执行安装
            if (UpdateHelper.isUpdateFileDownloaded(updateEntity) && confirmTextView.text != "立即更新") {
                DataLogUtils.uploadUpgradeLog(context, "install") //上传更新安装数据
                PackageInstaller.install(context, false, UpdateHelper.getUpdateDownloadPath(updateEntity), null)
            } else {
                showDownloadingStyle(updateEntity)
            }

            val buttonName: String = confirmTextView.text.toString()
            SensorsBridge.trackVersionUpdateDialogClick(
                buttonName = buttonName,
                keyDialogReminderTime = mUpdateEntity?.alert,
                keyDialogClose = if (mUpdateEntity?.isForce == true) "关闭且强退" else "仅关闭"
            )
        }

        if (invokeByViewCreated) {
            SensorsBridge.trackVersionUpdateDialogShow(
                keyDialogReminderTime = mUpdateEntity?.alert,
                keyDialogClose = if (mUpdateEntity?.isForce == true) "关闭且强退" else "仅关闭"
            )

            DataLogUtils.uploadUpgradeLog(context, "notice") //上传更新通知弹窗数据
        }

    }

    /**
     * 更新更新提示的文案
     */
    private fun updateUpdateHintView(
        binding: AppUpdateHintDialogBinding,
        updateEntity: AppEntity,
        isUpdateDownloaded: Boolean
    ) {
        val confirmText = if (isUpdateDownloaded) "立即安装" else "立即更新"
        val cancelText = if (isUpdateDownloaded) {
            if (updateEntity.isForce) "暂不安装，退出光环" else "暂不安装"
        } else {
            if (updateEntity.isForce) "暂不更新，退出光环" else "暂不更新"
        }

        binding.confirm.text = confirmText
        binding.downloadedHint.visibility = if (isUpdateDownloaded) View.VISIBLE else View.GONE
        binding.cancel.text = cancelText
    }

    /**
     * 显示更新下载中弹窗
     */
    private fun showDownloadingStyle(updateEntity: AppEntity) {
        mIsDisplayingDownloadingStyle = true

        val updatingBinding = mBinding.updatingContainerView
        val updateHintBinding = mBinding.updateHintContainerView

        updatingBinding.root.visibility = View.VISIBLE
        updateHintBinding.root.visibility = View.GONE

        updatingBinding.appTvCancel.setOnClickListener {
            DownloadManager.getInstance().cancel(updateEntity.url)
            if (updateEntity.isForce) {
                UpdateHelper.exitApp()
            } else {
                dismiss()
            }
        }

        if (NetworkUtils.isMobileConnected(context)) {
            ToastUtils.toast("当前使用移动数据进行下载")
        }

        UpdateHelper.createUpdate(updateEntity, false)
    }

    @SuppressLint("SetTextI18n")
    private fun updateDownloadingView(
        dialogBinding: AppUpdatingDialogBinding,
        downloadEntity: DownloadEntity,
        updateEntity: AppEntity
    ) {
        // 被取消任务的状态不用来更新页面
        if (DownloadStatus.cancel != downloadEntity.status) {
            val size = (downloadEntity.progress / 1024) / 1024F
            val df = DecimalFormat("0.00")
            dialogBinding.size.text = (df.format(size) + "MB")
            dialogBinding.remain.text = String.format(
                "剩余%s",
                SpeedUtils.getRemainSecondTime(
                    downloadEntity.size,
                    downloadEntity.progress,
                    downloadEntity.speed * 1024
                )
            )
            dialogBinding.progress.progress = (downloadEntity.percent * 10).roundToInt()

            val width = dialogBinding.progress.width
            val marLeft = (downloadEntity.percent / 100 * width)
            val anchorLp = dialogBinding.progressAnchor.layoutParams
            if (anchorLp is ConstraintLayout.LayoutParams) {
                anchorLp.leftMargin = marLeft.roundToInt()
                dialogBinding.progressAnchor.layoutParams = anchorLp
            }

            val fillingLp = dialogBinding.progressFilling.layoutParams
            fillingLp.width = (marLeft + DisplayUtils.dip2px(5F)).toInt()
            dialogBinding.progressFilling.layoutParams = fillingLp

            dialogBinding.percent.text = "${downloadEntity.percent} %"
        }

        if (DownloadStatus.done == downloadEntity.status) {
            DownloadManager.getInstance().cancel(downloadEntity.url, false, true, false)
            tryWithDefaultCatch {
                showUpdateHintStyle(requireContext(), updateEntity, false)
            }
        } else if (DownloadStatus.neterror == downloadEntity.status) {
            ToastUtils.toast("网络错误，请稍后重试")
        } else if (DownloadStatus.diskisfull == downloadEntity.status) {
            ToastUtils.toast("磁盘已满，请清理后重试")
        } else if (DownloadStatus.diskioerror == downloadEntity.status) {
            ToastUtils.toast("磁盘 IO 异常，请稍后重试")
        } else if (DownloadStatus.timeout == downloadEntity.status) {
            ToastUtils.toast("请求超时，请稍后重试")
        } else if (DownloadStatus.notfound == downloadEntity.status) {
            ToastUtils.toast("下载链接异常，请稍后重试")
        } else if (DownloadStatus.hijack == downloadEntity.status) {
            ToastUtils.toast("网络劫持，请稍后重试")
        }
    }

    companion object {
        const val UPDATE_ENTITY = "update_entity"

        fun newInstance(updateEntity: AppEntity, dismissCallback: EmptyCallback): UpdateDialogFragment {
            val fragment = UpdateDialogFragment()
            val bundle = Bundle()
            bundle.putParcelable(UPDATE_ENTITY, updateEntity)
            fragment.arguments = bundle
            fragment.mDismissCallback = dismissCallback
            return fragment
        }
    }

}