package com.gh.vspace

import android.annotation.SuppressLint
import android.content.Context
import android.os.Bundle
import android.text.SpannableStringBuilder
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.text.bold
import androidx.core.text.color
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.gh.common.exposure.ExposureUtils
import com.gh.common.exposure.ExposureUtils.DownloadType.DOWNLOAD
import com.gh.common.exposure.ExposureUtils.DownloadType.UPDATE
import com.gh.common.util.DataCollectionUtils
import com.gh.common.util.DirectUtils
import com.gh.common.util.NewFlatLogUtils
import com.gh.common.util.PackageInstaller
import com.gh.common.view.DownloadButton
import com.gh.download.DownloadManager
import com.gh.download.PackageObserver
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.fragment.BaseDraggableDialogFragment
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.utils.addMetaExtra
import com.gh.gamecenter.common.utils.toColor
import com.gh.gamecenter.common.utils.toJson
import com.gh.gamecenter.common.utils.viewModelProvider
import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.databinding.DialogVspaceBinding
import com.gh.gamecenter.entity.AppEntity
import com.gh.gamecenter.entity.GameEntity
import com.gh.gamecenter.eventbus.EBPackage
import com.halo.assistant.HaloApp
import com.lightgame.download.DataWatcher
import com.lightgame.download.DownloadConfig
import com.lightgame.download.DownloadEntity
import com.lightgame.download.DownloadStatus.*
import com.lightgame.utils.AppManager

class VSpaceDialogFragment : BaseDraggableDialogFragment() {

    private var mAppEntity: AppEntity? = null
    private val mDownloadUrl by lazy { mAppEntity?.url ?: "" }
    private val mBinding by lazy { DialogVspaceBinding.inflate(layoutInflater) }
    private val mDataWatcher = object : DataWatcher() {
        override fun onDataChanged(downloadEntity: DownloadEntity) {
            if (downloadEntity.url == mDownloadUrl && isAdded) {
                updateDownloadButton(downloadEntity)
            }
        }

        override fun onDataInit(downloadEntity: DownloadEntity) {
            onDataChanged(downloadEntity)
        }
    }

    override fun getRootView(): View = mBinding.root
    override fun getDragCloseView(): View = mBinding.dragClose

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

        mAppEntity = arguments?.get(KEY_ENTITY) as AppEntity
    }

    @SuppressLint("ClickableViewAccessibility")
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        return mBinding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val mViewModel = viewModelProvider<VSpaceDialogViewModel>()
        mViewModel.packageLiveData.observe(this) {
            if (it.packageName == VHelper.DEFAULT_VSPACE_PACKAGENAME) {
                dismissAllowingStateLoss()
            }
        }

        val spanBuilder = SpannableStringBuilder()
            .append("畅玩是一种更灵活、轻便的游戏方式\n")
            .append("下载")
            .color(R.color.text_subtitle.toColor(requireContext())) { bold { append(" 畅玩助手服务组件 ") } }
            .append("即可快速畅玩游戏~")

        mBinding.downloadBtn.text = "下载畅玩助手服务组件"
        mBinding.downloadBtn.buttonStyle = DownloadButton.ButtonStyle.NORMAL
        mBinding.descTv.text = spanBuilder
        mBinding.privacyPolicyTv.setOnClickListener {
            NewFlatLogUtils.logHaloFunEvent("halo_fun_download_dialog_privacy_click")
            DirectUtils.directToWebView(requireContext(), Constants.SMOOTH_GAME_PRIVACY_POLICY_ADDRESS)
        }

        val downloadSnapshot = DownloadManager.getInstance()
            .getDownloadEntitySnapshotByPackageName(VHelper.DEFAULT_VSPACE_PACKAGENAME)

        mBinding.downloadBtn.setOnClickListener {
            NewFlatLogUtils.logHaloFunEvent("halo_fun_download_dialog_download_click")

            val name = "畅玩助手V" + mAppEntity?.version
            val downloadId = PackageInstaller.createDownloadId(name)

            val downloadEntity = DownloadEntity()
            downloadEntity.url = mDownloadUrl
            downloadEntity.name = name
            downloadEntity.platform = "官方版"
            downloadEntity.gameId = "62bd412bbbf04747cd3de539"
            downloadEntity.path = PackageInstaller.getDownloadPathWithId(downloadId, "apk")
            downloadEntity.packageName = VHelper.DEFAULT_VSPACE_PACKAGENAME
            downloadEntity.addMetaExtra(DownloadConfig.KEY_PROGRESS_CALLBACK_INTERVAL, "200")

            // 确定下载类型
            val downloadType =
                if (arguments?.getBoolean(KEY_IS_UPDATE) == true) UPDATE else DOWNLOAD
            val gameEntity = GameEntity(downloadEntity.gameId, downloadEntity.name)
            gameEntity.gameVersion = mAppEntity?.version ?: ""

            val event = ExposureUtils.logADownloadExposureEvent(
                gameEntity,
                downloadEntity.platform,
                null,
                downloadType
            )

            downloadEntity.exposureTrace = event.toJson()

            AppExecutor.uiExecutor.executeWithDelay({
                DownloadManager.getInstance().cancel(mDownloadUrl)
                DownloadManager.getInstance().add(downloadEntity)
            }, 200)

            // 收集下载数据
            DataCollectionUtils.uploadDownload(HaloApp.getInstance(), downloadEntity, "开始")
        }

        if (arguments?.getBoolean(KEY_AUTO_DOWNLOAD) == true && downloadSnapshot == null) {
            mBinding.downloadBtn.performClick()
        }
    }

    override fun onStart() {
        super.onStart()
        DownloadManager.getInstance().addObserver(mDataWatcher)
    }

    override fun onStop() {
        super.onStop()
        DownloadManager.getInstance().removeObserver(mDataWatcher)
    }

    private fun updateDownloadButton(downloadEntity: DownloadEntity) {
        val downloadBtn = mBinding.downloadBtn
        downloadBtn.progress = (downloadEntity.progress * 10).toInt()
        when (downloadEntity.status) {
            downloading -> {
                downloadBtn.setText(R.string.pause)
                downloadBtn.progress = (downloadEntity.percent * 10).toInt()
                downloadBtn.buttonStyle = DownloadButton.ButtonStyle.DOWNLOADING_NORMAL
                downloadBtn.setOnClickListener {
                    DownloadManager.getInstance().pause(mDownloadUrl)
                }
            }

            pause -> {
                downloadBtn.setText(R.string.resume)
                downloadBtn.setOnClickListener {
                    DownloadManager.getInstance().resume(downloadEntity, true)
                }
            }

            overflow,
            timeout,
            neterror,
            waiting,
            subscribe -> {
                downloadBtn.setText(R.string.waiting)
                downloadBtn.buttonStyle = DownloadButton.ButtonStyle.DOWNLOADING_NORMAL
                downloadBtn.setOnClickListener {
                    DownloadManager.getInstance().resume(downloadEntity, false)
                }
            }
            done -> {
                downloadBtn.setText(R.string.install)
                downloadBtn.buttonStyle = DownloadButton.ButtonStyle.INSTALL_NORMAL
                downloadBtn.setOnClickListener {
                    PackageInstaller.install(requireContext(), downloadEntity)
                }
            }

            cancel,
            hijack,
            notfound,
            uncertificated,
            unqualified -> {
                downloadBtn.text = "下载畅玩助手服务组件"
                downloadBtn.buttonStyle = DownloadButton.ButtonStyle.NORMAL
                downloadBtn.setOnClickListener {
                    DownloadManager.getInstance().resume(downloadEntity, true)
                }
            }
            else -> {
                // do nothing
            }
        }
    }

    companion object {
        const val KEY_ENTITY = "entity"
        const val KEY_AUTO_DOWNLOAD = "auto_download"
        const val KEY_IS_UPDATE = "is_update"

        @JvmStatic
        fun showDownloadDialog(
            context: Context?,
            appEntity: AppEntity,
            autoDownload: Boolean = false,
            isUpdate: Boolean = false
        ) {
            val fragmentActivity: FragmentActivity = if (context is FragmentActivity) {
                context
            } else {
                val currentActivity = AppManager.getInstance().currentActivity()
                if (currentActivity is FragmentActivity) {
                    currentActivity
                } else {
                    throw IllegalStateException("current activity context must be FragmentActivity")
                }
            }

            // 防止重复弹出
            if (hasDialogDisplayedInCurrentActivity(fragmentActivity)) return

            NewFlatLogUtils.logHaloFunEvent("halo_fun_download_dialog_show")

            val downloadDialog = VSpaceDialogFragment().apply {
                arguments = Bundle().apply {
                    putParcelable(KEY_ENTITY, appEntity)
                    putBoolean(KEY_AUTO_DOWNLOAD, autoDownload)
                    putBoolean(KEY_IS_UPDATE, isUpdate)
                }
            }
            downloadDialog.show(
                fragmentActivity.supportFragmentManager,
                VSpaceDialogFragment::class.java.name
            )
        }

        private fun hasDialogDisplayedInCurrentActivity(fragmentActivity: FragmentActivity): Boolean {
            val fragments: List<Fragment> = fragmentActivity.supportFragmentManager.fragments
            fragments.forEach { fragment ->
                if (fragment is VSpaceDialogFragment) return true
            }
            return false
        }
    }

    internal class VSpaceDialogViewModel : ViewModel() {
        val packageLiveData = MutableLiveData<EBPackage>()
        private val mPackageChangedListener by lazy {
            PackageObserver.PackageChangeListener {
                packageLiveData.postValue(it)
            }
        }

        init {
            PackageObserver.registerPackageChangeChangeListener(mPackageChangedListener)
        }

        override fun onCleared() {
            super.onCleared()

            PackageObserver.unregisterPackageChangeChangeListener(mPackageChangedListener)
        }
    }

}