package com.gh.vspace

import android.annotation.SuppressLint
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
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.util.PackageUtils
import com.gh.gamecenter.feature.view.DownloadButton
import com.gh.download.DownloadManager
import com.gh.download.PackageObserver
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.activity.BaseActivity
import com.gh.gamecenter.common.base.fragment.BaseDraggableDialogFragment
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.databinding.DialogVspaceBinding
import com.gh.gamecenter.entity.AppEntity
import com.gh.gamecenter.feature.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 mAppEntity64: AppEntity? = null
    private var mAppEntity32: AppEntity? = null
    private var mGameId: String = ""
    private var mGameName: String = ""
    private var mBit: String = "" // 畅玩游戏位数
    private var mIsUpdate = false
    private val mDownloadUrl64 by lazy { mAppEntity64?.url ?: "" }
    private val mDownloadUrl32 by lazy { mAppEntity32?.url ?: "" }
    private val mBinding by lazy { DialogVspaceBinding.inflate(layoutInflater) }
    private val mDataWatcher = object : DataWatcher() {
        override fun onDataChanged(downloadEntity: DownloadEntity) {
            if (((mAppEntity64 != null && downloadEntity.url == mDownloadUrl64) || (mAppEntity64 == null && downloadEntity.url == mDownloadUrl32)) && 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)

        mAppEntity64 = arguments?.get(KEY_APP_ENTITY_64) as? AppEntity
        mAppEntity32 = arguments?.get(KEY_APP_ENTITY_32) as? AppEntity
        mGameId = arguments?.getString(EntranceConsts.KEY_GAME_ID) ?: ""
        mGameName = arguments?.getString(EntranceConsts.KEY_GAME_NAME) ?: ""
        mBit = arguments?.getString(VHelper.KEY_BIT) ?: ""
        mIsUpdate = arguments?.getBoolean(KEY_IS_UPDATE) == true
    }

    @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) {
                if (mIsUpdate) showVSpace32UpdateDialogIfNeeded() else showVSpace32DownloadDialogIfNeeded()
                dismissAllowingStateLoss()
            }
            if (it.packageName == VHelper.VSPACE_32BIT_PACKAGENAME) {
                dismissAllowingStateLoss()
            }
        }

        mBinding.downloadBtn.text = "下载畅玩助手服务组件"
        mBinding.downloadBtn.buttonStyle = DownloadButton.ButtonStyle.NORMAL
        mBinding.descTv.text = "《$mGameName》需先安装畅玩服务组件，安装后即可进入游戏体验新鲜功能~"
        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(if (mAppEntity64 != null) VHelper.DEFAULT_VSPACE_PACKAGENAME else VHelper.VSPACE_32BIT_PACKAGENAME)

        mBinding.downloadBtn.setOnClickListener {
            NewFlatLogUtils.logHaloFunEvent("halo_fun_download_dialog_download_click")
            SensorsBridge.trackEvent("HaloFunDownloadDialogDownloadClick", "game_id", mGameId, "game_name", mGameName)

            // 确定下载类型
            val downloadType = if (mIsUpdate) UPDATE else DOWNLOAD
            var downloadEntity64: DownloadEntity? = null
            var downloadEntity32: DownloadEntity? = null

            if (mAppEntity64 != null) {
                downloadEntity64 = getDownloadEntity(true)

                val gameEntity64 = GameEntity(downloadEntity64.gameId, downloadEntity64.name)
                gameEntity64.gameVersion = mAppEntity64?.version ?: ""

                downloadEntity64.exposureTrace = ExposureUtils.logADownloadExposureEvent(
                    gameEntity64,
                    downloadEntity64.platform,
                    null,
                    downloadType
                ).toJson()

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

            val is32VSpaceInstalled = PackageUtils.isInstalledFromAllPackage(context, VHelper.VSPACE_32BIT_PACKAGENAME)
            if (mBit == "32" && mAppEntity32 != null && !(is32VSpaceInstalled && !mIsUpdate)) {
                downloadEntity32 = getDownloadEntity(false)

                // 非32位单独下载时下载完成不弹出安装界面
                if (mAppEntity64 != null) {
                    downloadEntity32.addMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE, Constants.VSPACE_32_DOWNLOAD_ONLY)
                }

                val gameEntity32 = GameEntity(downloadEntity32.gameId, downloadEntity32.name)
                gameEntity32.gameVersion = mAppEntity32?.version ?: ""

                downloadEntity32.exposureTrace = ExposureUtils.logADownloadExposureEvent(
                    gameEntity32,
                    downloadEntity32.platform,
                    null,
                    downloadType
                ).toJson()

                DataCollectionUtils.uploadDownload(HaloApp.getInstance(), downloadEntity32, "开始")
            }

            AppExecutor.uiExecutor.executeWithDelay({
                if (downloadEntity64 != null) {
                    DownloadManager.getInstance().cancel(mDownloadUrl64)
                    DownloadManager.getInstance().add(downloadEntity64)
                }
                if (downloadEntity32 != null) {
                    DownloadManager.getInstance().cancel(mDownloadUrl32)
                    DownloadManager.getInstance().add(downloadEntity32)
                }
            }, 200)
        }

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

    private fun getDownloadEntity(is64Bit: Boolean) = DownloadEntity().apply {
        url = if (is64Bit) mDownloadUrl64 else mDownloadUrl32
        name =
            "畅玩助手V" + (if (is64Bit) mAppEntity64?.version else mAppEntity32?.version) + "(${if (is64Bit) 64 else 32}位)"
        platform = "官方版"
        gameId = "62bd412bbbf04747cd3de539"
        path = PackageInstaller.getDownloadPathWithId(PackageInstaller.createDownloadId(name), "apk")
        packageName = if (is64Bit) VHelper.DEFAULT_VSPACE_PACKAGENAME else VHelper.VSPACE_32BIT_PACKAGENAME
        addMetaExtra(DownloadConfig.KEY_PROGRESS_CALLBACK_INTERVAL, "200")
    }

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

        // 上面监听安装包名变化的 LiveData 监听有可能被冲掉了
        // 手动再检查一下安装状态，避免出现已安装但是没有 dismiss 弹窗的问题
        if (PackageUtils.isInstalled(requireContext(), VHelper.DEFAULT_VSPACE_PACKAGENAME)) {
            if (mIsUpdate) showVSpace32UpdateDialogIfNeeded() else showVSpace32DownloadDialogIfNeeded()
            dismissAllowingStateLoss()
        }
        if (PackageUtils.isInstalled(requireContext(), VHelper.VSPACE_32BIT_PACKAGENAME)) {
            dismissAllowingStateLoss()
        }
    }

    private fun showVSpace32DownloadDialogIfNeeded() {
        val is32VSpaceInstalled =
            PackageUtils.isInstalledFromAllPackage(requireContext(), VHelper.VSPACE_32BIT_PACKAGENAME)
        if (!is32VSpaceInstalled && mBit == "32" && mAppEntity32 != null && !mAppEntity32?.url.isNullOrEmpty()) {
            VSpace32DialogFragment.showDownloadDialog(
                requireContext(),
                mAppEntity32!!,
                gameId = mGameId,
                gameName = mGameName
            )
        }
    }

    private fun showVSpace32UpdateDialogIfNeeded() {
        if (mBit == "32" && mAppEntity32 != null && !mAppEntity32?.url.isNullOrEmpty()) {
            VSpaceUpdate32DialogFragment.showDownloadDialog(
                requireContext(),
                mAppEntity32!!,
                gameId = mGameId,
                gameName = mGameName
            )
        }
    }

    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(downloadEntity.url)
                }
            }

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

            overflow,
            timeout,
            neterror,
            diskioerror,
            diskisfull,
            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

                SensorsBridge.trackEvent("HaloFunDownloadDone")

                downloadBtn.setOnClickListener {
                    PackageInstaller.install(requireContext(), downloadEntity)
                    SensorsBridge.trackEvent("HaloFunInstallButtonClick")
                }
            }

            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_APP_ENTITY_64 = "app_entity_64"
        const val KEY_APP_ENTITY_32 = "app_entity_32"
        const val KEY_AUTO_DOWNLOAD = "auto_download"
        const val KEY_IS_UPDATE = "is_update"

        @JvmStatic
        fun showDownloadDialog(
            context: Context?,
            appEntity64: AppEntity?,
            appEntity32: AppEntity?,
            autoDownload: Boolean = false,
            isUpdate: Boolean = false,
            gameId: String = "",
            gameName: String = "",
            bit: String = ""
        ) {
            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")

            if (context is BaseActivity) {
                SensorsBridge.trackEvent(
                    "HaloFunDownloadDialogShow",
                    "last_page_name", context::class.java.simpleName,
                    "last_page_id", context.getUniqueId(),
                    "last_page_business_id", context.getBusinessId().first,
                )
            }


            val downloadDialog = VSpaceDialogFragment().apply {
                arguments = Bundle().apply {
                    if (appEntity64 != null) putParcelable(KEY_APP_ENTITY_64, appEntity64)
                    if (appEntity32 != null) putParcelable(KEY_APP_ENTITY_32, appEntity32)
                    putString(EntranceConsts.KEY_GAME_ID, gameId)
                    putString(EntranceConsts.KEY_GAME_NAME, gameName)
                    putString(VHelper.KEY_BIT, bit)
                    putBoolean(KEY_AUTO_DOWNLOAD, autoDownload)
                    putBoolean(KEY_IS_UPDATE, isUpdate)
                }
            }
            downloadDialog.show(
                fragmentActivity.supportFragmentManager,
                VSpaceDialogFragment::class.java.name
            )
        }

        @JvmStatic
        fun showDownloadDialog(
            context: Context?,
            appEntity64: AppEntity?,
            appEntity32: AppEntity?,
            gameEntity: GameEntity?,
            autoDownload: Boolean = false,
            isUpdate: Boolean = false
        ) {
            showDownloadDialog(
                context,
                appEntity64,
                appEntity32,
                autoDownload,
                isUpdate,
                gameEntity?.id ?: "",
                gameEntity?.name ?: "",
                gameEntity?.getApk()?.get(0)?.bit ?: ""
            )
        }

        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)
        }
    }

}