package com.gh.gamecenter.gamedetail.dialog

import android.app.Dialog
import android.content.DialogInterface
import android.content.Intent
import android.os.Bundle
import android.view.*
import android.widget.ImageView
import android.widget.TextView
import androidx.lifecycle.ViewModelProvider
import com.gh.common.util.*
import com.gh.common.xapk.XapkInstaller
import com.gh.common.xapk.XapkUnzipStatus
import com.gh.download.DownloadManager
import com.gh.gamecenter.R
import com.gh.gamecenter.ShellActivity
import com.gh.gamecenter.ShellActivity.Type
import com.gh.gamecenter.common.base.fragment.BaseDraggableDialogFragment
import com.gh.gamecenter.common.entity.LinkEntity
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.common.utils.asVGame
import com.gh.gamecenter.common.utils.viewModelProviderFromParent
import com.gh.gamecenter.core.utils.SpeedUtils
import com.gh.gamecenter.databinding.FragmentDialogSpecialDownloadBinding
import com.gh.gamecenter.feature.entity.GameDetailServer
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.LibaoEntity
import com.gh.gamecenter.feature.entity.MeEntity
import com.gh.gamecenter.feature.view.TrapezoidDownloadButton
import com.gh.gamecenter.gamedetail.GameDetailViewModel
import com.gh.gamecenter.gamedetail.entity.GameDetailTabEntity
import com.gh.gamecenter.gamedetail.fuli.kaifu.ServersCalendarActivity
import com.gh.gamecenter.gamedetail.libao.LibaoListFragment
import com.gh.gamecenter.manager.PackagesManager
import com.gh.ndownload.NDownloadService
import com.gh.ndownload.suspendwindow.utils.NDownloadSuspendWindowHelper
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

class SpecialDownloadDialogFragment : BaseDraggableDialogFragment() {

    private var boundedGameEntity: GameEntity? = null

    private var downloadBtn: TrapezoidDownloadButton? = null
    private var mainTipsView: View? = null

    private var viewModel: SpecialDownloadDialogViewModel? = null
    private var visibilityViewModel: SpecialDownloadVisibilityViewModel? = null
    private var gameDetailViewModel: GameDetailViewModel? = null

    private var installedVersionMisMatched = false

    private var showSuspendIconWindowOnResume = false

    private val subContainerViewIdArray = arrayOf(
        R.id.rightBottomTrapezoidContainer,
        R.id.leftTrapezoidContainer,
        R.id.centerTrapezoidContainer,
        R.id.rightTrapezoidContainer
    )

    private val pausedText by lazy {
        context?.getString(com.gh.gamecenter.feature.R.string.paused)
    }

    private var dataWatcher = object : DataWatcher() {
        override fun onDataChanged(downloadEntity: DownloadEntity?) {
            if (downloadEntity?.gameId == boundedGameEntity?.id) {
                when (downloadEntity?.status) {
                    DownloadStatus.pause -> {
                        val roundedProgress = Math.ceil(downloadEntity.percent).toInt()
                        downloadBtn?.setProgress((downloadEntity.percent / 100).toFloat())
                        downloadBtn?.setText("${roundedProgress}% $pausedText")
                    }

                    DownloadStatus.done -> {
                        downloadBtn?.setProgress(1.0F)
                        downloadBtn?.setText(context?.getString(com.gh.gamecenter.feature.R.string.install) ?: "")
                        val xapkStatus = downloadEntity.meta[XapkInstaller.XAPK_UNZIP_STATUS]
                        when {
                            (XapkUnzipStatus.SUCCESS.name == xapkStatus || XapkUnzipStatus.INSTALLED.name == xapkStatus) && XapkInstaller.isInstalling(downloadEntity.path) -> {
                                downloadBtn?.setText(context?.getString(com.gh.gamecenter.feature.R.string.installing) ?: "")
                            }
                            XapkUnzipStatus.UNZIPPING.name == xapkStatus -> {
                                downloadBtn?.setText(context?.getString(com.gh.gamecenter.feature.R.string.unzipping) ?: "")
                            }
                        }
                    }

                    DownloadStatus.cancel -> {
                        if (PackageUtils.isInstalled(context, downloadEntity.packageName)) {
                            showLaunchStyle(downloadEntity.packageName)
                        } else {
                            dismissAllowingStateLoss()
                        }
                    }

                    else -> {
                        downloadBtn?.setProgress((downloadEntity!!.percent / 100).toFloat())
                        downloadBtn?.setText(SpeedUtils.getSpeed(downloadEntity?.speed ?: 0))
                    }
                }
            }
        }

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

    private val binding: FragmentDialogSpecialDownloadBinding by lazy {
        FragmentDialogSpecialDownloadBinding.inflate(layoutInflater)
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return binding.root
    }

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        val dialog = super.onCreateDialog(savedInstanceState)

        // Remove the dim background (mask)
        dialog.window?.apply {
            clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
            setFlags(
                WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
                WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
            )
            isCancelable = false
            setGravity(Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL)
        }
        dialog.setCancelable(false)
        dialog.setCanceledOnTouchOutside(false)

        return dialog
    }

    override fun onBack(): Boolean {
        requireActivity().onBackPressed()
        return true
    }

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

        boundedGameEntity = arguments?.getParcelable(KEY_GAME_ENTITY)

        val factory = GameDetailViewModel.Factory(
            HaloApp.getInstance().application,
            boundedGameEntity?.id,
            boundedGameEntity
        )
        gameDetailViewModel = viewModelProviderFromParent(factory, boundedGameEntity?.id ?: "")

        val installHint = arguments?.getParcelable(KEY_INSTALL_HINT) ?: LinkEntity()

        binding.collapseIv.setOnClickListener {
            dismissAllowingStateLoss()
        }

        visibilityViewModel = viewModelProviderFromParent()
        visibilityViewModel?.updateSpecialDownloadDialogVisibility(true)

        viewModel = ViewModelProvider(
            this, SpecialDownloadDialogViewModel.Factory(
                boundedGameEntity!!,
                arguments?.getString(KEY_ZONE_URL),
                arguments?.getParcelableArrayList(KEY_LIBAO_LIST),
                arguments?.getParcelable(KEY_SERVER)
            )
        )[SpecialDownloadDialogViewModel::class.java]

        viewModel?.displayContentLiveData?.observe(viewLifecycleOwner) { contentList ->
            binding.contentContainer.removeAllViews()
            binding.contentContainer.addView(getContentView(contentList))

            refreshViewBinding(contentList)

            mainTipsView?.setOnClickListener {
                DirectUtils.directToLinkPage(
                    requireContext(),
                    installHint,
                    "游戏详情安装提示组件",
                    ""
                )
                trackEvent(boundedGameEntity!!, "安装问题提示", true)
            }
        }

        boundedGameEntity?.let {
            trackEvent(it)
        }
    }

    override fun onResume() {
        super.onResume()

        // 检查下载列表中是否有当前游戏，没有且本地不匹配当前版本的话，dismiss dialog
        val downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(boundedGameEntity)
        val packageName = boundedGameEntity?.getUniquePackageName()

        viewModel?.updateDisplayContent(requireContext())

        if (showSuspendIconWindowOnResume
            && NDownloadSuspendWindowHelper.canDrawOverLayer(requireContext())
            && downloadEntity != null) {

            val intent = Intent(requireContext(), NDownloadService::class.java)
            intent.putExtra(DownloadConfig.KEY_DOWNLOAD_ENTRY, downloadEntity)
            intent.putExtra(NDownloadService.KEY_SERVICE_ACTION, NDownloadService.ACTION_SHOW_SUSPEND_WINDOW)

            requireContext().startService(intent)
            showSuspendIconWindowOnResume = false
        }

        if (downloadEntity == null) {
            if (boundedGameEntity?.getApk()?.firstOrNull()?.version
                != PackageUtils.getVersionNameByPackageName(packageName)
            ) {
                installedVersionMisMatched = true
                dismissAllowingStateLoss()
            } else {
                if (PackageUtils.isInstalled(requireContext(), packageName)) {
                    showLaunchStyle(packageName ?: "")
                }
            }
        }

        DownloadManager.getInstance().addObserver(dataWatcher)
    }

    private fun showLaunchStyle(packageName: String) {
        downloadBtn?.setProgress(1.0F)
        downloadBtn?.setText(context?.getString(com.gh.gamecenter.feature.R.string.launch) ?: "")
        downloadBtn?.setOnClickListener {
            PackageLauncher.launchApp(context = requireContext(), packageName = packageName)
            dismissAllowingStateLoss()
        }
    }

    override fun onPause() {
        super.onPause()

        DownloadManager.getInstance().removeObserver(dataWatcher)
    }

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

        if (!installedVersionMisMatched) {
            visibilityViewModel?.updateSpecialDownloadDialogVisibility(false)
        }
    }

    override fun getRootView() = binding.root
    override fun getDragCloseView() = null

    private fun getContentView(contentList: ArrayList<SpecialDownloadDialogViewModel.Content>?): View {
        return if (contentList.isNullOrEmpty()) {
            layoutInflater.inflate(R.layout.fragment_dialog_special_download_2, null)
        } else if (contentList.size == 1) {
            layoutInflater.inflate(R.layout.fragment_dialog_special_download_3, null)
        } else {
            layoutInflater.inflate(R.layout.fragment_dialog_special_download_multi, null)
        }
    }

    private fun refreshViewBinding(contentList: ArrayList<SpecialDownloadDialogViewModel.Content>) {
        downloadBtn = binding.root.findViewById(R.id.downloadBtn)
        mainTipsView = binding.root.findViewById(R.id.tipsContainer)

        val subTipsViewList = ArrayList<ViewGroup>()

        for (id in subContainerViewIdArray) {
            val subContainerView = binding.root.findViewById<ViewGroup>(id)
            if (subContainerView != null) {
                subTipsViewList.add(subContainerView)
            }
        }

        // 如果内容数量大于子容器数量，移除多余的子容器 （在中间的梯形）
        if (subTipsViewList.size > contentList.size) {
            val subCenterTrapezoidContainer = binding.root.findViewById<ViewGroup>(R.id.centerTrapezoidContainer)
            subCenterTrapezoidContainer?.let {
                it.visibility = View.GONE
                subTipsViewList.remove(it)
            }
        }

        for ((index, subTipsView) in subTipsViewList.withIndex()) {
            val titleIv = subTipsView.findViewById<ImageView>(R.id.titleIv)
            val hintTv = subTipsView.findViewById<TextView>(R.id.hintTv)
            val content = contentList[index]

            when {
                content.zoneUrl != null -> {
                    titleIv.setImageResource(R.drawable.ic_special_download_text_game_stretegy)
                    hintTv.setText(getString(R.string.special_download_tips_head_to_immediately))
                    subTipsView.setOnClickListener {
                        DirectUtils.directToWebView(requireContext(), content.zoneUrl)
                        trackEvent(boundedGameEntity!!, "游戏专区", true)
                    }
                }

                content.libaoList != null -> {
                    titleIv.setImageResource(R.drawable.ic_special_download_text_gift)
                    hintTv.setText(getString(R.string.special_download_tips_collect_immediately))
                    subTipsView.setOnClickListener {
                        val tabList = gameDetailViewModel?.gameDetailTabListLiveData?.value?.data
                        if (tabList?.find { it.type == GameDetailTabEntity.TYPE_GIFT } != null) {
                            gameDetailViewModel?.performTabSelected(GameDetailTabEntity.TYPE_GIFT)
                        } else {
                            val bundle = LibaoListFragment.getBundle(boundedGameEntity, false)
                            startActivity(ShellActivity.getIntent(requireContext(), Type.SIMPLE_LIBAO_LIST, bundle))
                        }
                        trackEvent(boundedGameEntity!!, "游戏礼包", true)
                    }
                }

                content.server != null -> {
                    titleIv.setImageResource(R.drawable.ic_special_download_text_server_canlendar)
                    hintTv.setText(getString(R.string.special_download_tips_check_detail))
                    subTipsView.setOnClickListener {
                        requireContext().startActivity(
                            ServersCalendarActivity.getIntent(
                                requireContext(),
                                boundedGameEntity!!,
                                content.server,
                                MeEntity()
                            )
                        )
                        trackEvent(boundedGameEntity!!, "开服表", true)
                    }
                }

                content.isAlertPermissionGranted == false -> {
                    titleIv.setImageResource(R.drawable.ic_special_download_text_enable_fast_download)
                    hintTv.text = getString(R.string.special_download_tips_click_to_enable)
                    subTipsView.setOnClickListener {
                        showSuspendIconWindowOnResume = true
                        NDownloadSuspendWindowHelper
                            .requestDrawOverlayPermission(
                                requireActivity(),
                                0,
                                "下载组件"
                            )
                        trackEvent(boundedGameEntity!!, "悬浮窗权限提示", true)
                    }
                }
            }
        }

        downloadBtn?.setOnClickListener {
            val downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(boundedGameEntity)
            downloadEntity?.let {
                when (it.status) {
                    DownloadStatus.pause -> {
                        DownloadManager.getInstance().resume(it, false)
                    }

                    DownloadStatus.done -> {
                        PackageInstaller.install(
                            context = requireContext(),
                            downloadEntity = it
                        )
                    }

                    else -> {
                        DownloadManager.getInstance().pause(it.url)
                    }
                }
            }
        }
    }

    override fun onDarkModeChanged() {
        super.onDarkModeChanged()

        binding.contentContainer.setBackgroundResource(com.gh.gamecenter.common.R.color.ui_surface)
        binding.collapseIv.setImageResource(R.drawable.ic_special_download_collapse)
    }

    private fun trackEvent(gameEntity: GameEntity, contentType: String = "", isClick: Boolean = false) {
        val downloadSnapshot =
            DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity.getApk().firstOrNull()?.url)
        val asVGame = downloadSnapshot?.asVGame() == true

        if (isClick) {
            val statusInChinese = when {
                downloadSnapshot?.status == DownloadStatus.downloading -> {
                    "下载中"
                }

                downloadSnapshot == null
                        || downloadSnapshot.status == DownloadStatus.done -> {
                    if (PackagesManager.isInstalled(gameEntity.getUniquePackageName())) {
                        "已安装"
                    } else {
                        "待安装"
                    }
                }

                else -> {
                    "暂停中"
                }
            }

            SensorsBridge.trackDownloadComponentsContentClick(
                gameId = gameEntity.id,
                gameName = gameEntity.name ?: "unknown",
                gameSchemaType = gameEntity.gameBitChinese,
                downloadStatus = gameEntity.downloadStatusChinese,
                gameType = gameEntity.categoryChinese,
                downloadType = if (asVGame) "畅玩下载" else "本地下载",
                contentType = contentType,
                downloadTaskStatus = statusInChinese
            )
        } else {
            SensorsBridge.trackDownloadComponentsShow(
                gameId = gameEntity.id,
                gameName = gameEntity.name ?: "unknown",
                gameSchemaType = gameEntity.gameBitChinese,
                downloadStatus = gameEntity.downloadStatusChinese,
                gameType = gameEntity.categoryChinese,
                downloadType = if (asVGame) "畅玩下载" else "本地下载",
            )
        }
    }

    companion object {

        private const val KEY_GAME_ENTITY = "game_entity"
        private const val KEY_INSTALL_HINT = "install_hint"
        private const val KEY_ZONE_URL = "zone_url"
        private const val KEY_LIBAO_LIST = "libao_list"
        private const val KEY_SERVER = "server"

        fun newInstance(
            gameEntity: GameEntity,
            installHint: LinkEntity,
            zoneUrl: String?,
            libaoList: ArrayList<LibaoEntity>?,
            server: GameDetailServer?
        ): SpecialDownloadDialogFragment {
            return SpecialDownloadDialogFragment().apply {
                arguments = Bundle().apply {
                    putParcelable(KEY_INSTALL_HINT, installHint)
                    putParcelable(KEY_GAME_ENTITY, gameEntity)
                    putString(KEY_ZONE_URL, zoneUrl)
                    putParcelableArrayList(KEY_LIBAO_LIST, libaoList)
                    putParcelable(KEY_SERVER, server)
                }
            }
        }
    }

}