package com.gh.download.dialog

import android.annotation.SuppressLint
import android.content.Context
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.Animation
import android.view.animation.AnimationUtils
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.*
import androidx.recyclerview.widget.RecyclerView.SmoothScroller
import com.gh.common.util.DialogUtils
import com.gh.common.util.DirectUtils
import com.gh.download.DownloadManager
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.activity.ToolBarActivity
import com.gh.gamecenter.common.base.fragment.BaseDraggableDialogFragment
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.utils.goneIf
import com.gh.gamecenter.common.utils.observeNonNull
import com.gh.gamecenter.common.utils.safelyGetInRelease
import com.gh.gamecenter.common.utils.throwExceptionInDebug
import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.core.utils.TimeElapsedHelper
import com.gh.gamecenter.databinding.DialogDownloadBinding
import com.gh.gamecenter.entity.GamePlatform
import com.gh.gamecenter.eventbus.EBPackage
import com.gh.gamecenter.feature.entity.ApkEntity
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.halo.assistant.HaloApp
import com.lightgame.download.DataWatcher
import com.lightgame.download.DownloadEntity
import com.lightgame.download.DownloadStatus
import com.lightgame.utils.AppManager
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode

class DownloadDialog : BaseDraggableDialogFragment() {

    private lateinit var mGameEntity: GameEntity
    private lateinit var mViewModel: DownloadViewModel
    private lateinit var mBinding: DialogDownloadBinding

    private lateinit var mElapsedHelper: TimeElapsedHelper

    private var mAdapter: DownloadDialogAdapter? = null
    private var mTraceEvent: ExposureEvent? = null
    private var mPlatformListAutoDownload: Boolean = true
    private var mPlatformList: List<GamePlatform>? = null
    private var mParentBundle: Bundle? = null

    // 合集页面保持和后台一样的顺序
    private var mCollectionAdapter: DownloadDialogAdapter? = null

    /**
     * 例子：在首页跳转至专题详情点击下载
     * mEntrance-> （首页）+（专题详情）
     * mLocation->  专题名称：游戏名称
     *
     * 注意：location 只用于下载统计，具体的 entrance = entrance + path
     */
    private var mEntrance: String = "" // 入口位置
    private var mLocation: String = "" // 最终位置

    private var onDownloadClickAction: ((Boolean) -> Unit)? = null


    private val mDataWatcher = object : DataWatcher() {
        override fun onDataChanged(downloadEntity: DownloadEntity) {
            if (downloadEntity.gameId == mGameEntity?.id &&
                DownloadStatus.delete != DownloadManager.getInstance().getStatus(downloadEntity.url)
            ) {
                mAdapter?.listData?.forEachIndexed { index, entity ->
                    if (entity.normal?.packageName == downloadEntity.packageName
                        || entity.installed?.packageName == downloadEntity.packageName
                    ) {
                        mAdapter?.notifyItemChanged(index)
                    }
                }

                mCollectionAdapter?.listData?.forEachIndexed { index, entity ->
                    if (entity.normal?.packageName == downloadEntity.packageName
                        || entity.installed?.packageName == downloadEntity.packageName
                    ) {
                        mCollectionAdapter?.notifyItemChanged(index)
                    }
                }
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        EventBus.getDefault().register(this)
        super.onCreate(savedInstanceState)

        mParentBundle = requireActivity().intent.extras?.getBundle(ToolBarActivity.NORMAL_FRAGMENT_BUNDLE)
        mPlatformListAutoDownload = mParentBundle?.getBoolean(EntranceConsts.KEY_PLATFORMS_AUTO_DOWNLOAD, true) ?: true
        mPlatformList = if (mPlatformListAutoDownload) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                mParentBundle?.getParcelableArrayList(EntranceConsts.KEY_PLATFORMS, GamePlatform::class.java)
            } else {
                mParentBundle?.getParcelableArrayList(EntranceConsts.KEY_PLATFORMS)
            }
        } else {
            emptyList()
        }
        mGameEntity = requireArguments().getParcelable(GameEntity::class.java.simpleName)!!
        mEntrance = requireArguments().getString(EntranceConsts.KEY_ENTRANCE) ?: ""
        mLocation = requireArguments().getString(EntranceConsts.KEY_LOCATION) ?: ""
        mTraceEvent = requireArguments().getParcelable(EntranceConsts.KEY_TRACE_EVENT) ?: null

        val factory = DownloadViewModel.Factory(HaloApp.getInstance().application, mGameEntity)
        mViewModel = ViewModelProviders.of(this, factory).get(DownloadViewModel::class.java)
        if (savedInstanceState != null) {
            mViewModel.getAllPackageName()
        }
        mViewModel.listLiveData.observeNonNull(this, callback = { itemList ->
            mAdapter =
                DownloadDialogAdapter(requireContext(), mViewModel, itemList, false, mTraceEvent, mEntrance, mLocation, onDownloadClickAction)
            mBinding.contentList.layoutManager = createLayoutManager(itemList)
            mBinding.contentList.adapter = mAdapter
            performAutoDownload(itemList, mBinding.contentList)
        })

        mViewModel.collectionLiveData.observe(this, Observer { collection ->
            if (collection != null) {
                postBrowseMta()

                mBinding.title.text = collection.name
                val saveApkList = collection.saveApkEntity
                throwExceptionInDebug("collection content must not be empty", saveApkList.isNullOrEmpty())

                val itemList: MutableList<DownloadDialogItemData> = ArrayList()
                saveApkList?.forEach { apk ->
                    mViewModel.setSortValueToApkEntity(apk)
                    itemList.add(DownloadDialogItemData(normal = apk))
                }
                val count = itemList.count { it.normal?.recommend != null }
                if (count % 2 != 0) {
                    itemList.add(DownloadDialogItemData(normal = ApkEntity(order = DownloadViewModel.SORT_RECOMMEND_EMPTY)))
                }

                itemList.sortWith(Comparator { o1, o2 ->
                    (o2.normal?.order ?: 0) - (o1.normal?.order ?: 0)
                })

                if (collection.downloadInstruction.isNotEmpty()) {
                    itemList.add(DownloadDialogItemData(instruction = collection.downloadInstruction))
                }

                mCollectionAdapter = DownloadDialogAdapter(
                    requireContext(),
                    mViewModel,
                    itemList,
                    true,
                    mTraceEvent,
                    mEntrance,
                    mLocation,
                    onDownloadClickAction
                )
                mBinding.collectionList.layoutManager = createLayoutManager(itemList)
                mBinding.collectionList.adapter = mCollectionAdapter
                performAutoDownload(itemList, mBinding.collectionList)
                if (mAdapter != null) collectionEnterAnimation()
            } else {
                mBinding.title.text = ("选择下载" + mGameEntity?.pluginDesc + "版本")

                mCollectionAdapter = null
                collectionExitAnimation()
            }
        })
        mViewModel.dismissLiveData.observe(this, Observer {
            dismissAllowingStateLoss()
        })

        mElapsedHelper = TimeElapsedHelper()
    }

    //自动下载
    private fun performAutoDownload(itemList: List<DownloadDialogItemData>, recyclerView: RecyclerView) {
        val platformList = this.mPlatformList
        if (platformList.isNullOrEmpty()) return
        AppExecutor.uiExecutor.executeWithDelay({
            recyclerView.adapter?.let {
                for (i in 0 until it.itemCount) {
                    val apkEntity = itemList.safelyGetInRelease(i)?.normal ?: continue
                    val apkCollection = apkEntity.apkCollection
                    val platformName = platformList[0].name
                    val packageName = platformList[0].packageName
                    if (apkCollection != null) {// 插件集合首先切换到集合列表，再自动下载插件
                        if (apkCollection.name == platformName) {// 第一个需要自动下载的插件名称与插件集合名称相同
                            scrollAndDownload(recyclerView, false, i)
                            break
                        } else {
                            // 插件集合列表中存在需要自动下载的插件
                            val matched = apkCollection.saveApkEntity?.any { entity ->
                                entity.getPlatformName() == platformName || entity.packageName == packageName
                            }

                            if (matched == true) {
                                scrollAndDownload(recyclerView, false, i)
                                break
                            }
                        }
                    }
                    // 自动下载符合条件的插件
                    val matchPlatformIndex = platformList.indexOfFirst { platform ->
                        platform.name == apkEntity.getPlatformName() || platform.packageName == apkEntity.packageName
                    }
                    if (matchPlatformIndex != -1) {
                        scrollAndDownload(recyclerView, true, i)
                    }
                }
            }
        }, 200)
    }

    private fun scrollAndDownload(recyclerView: RecyclerView, isResetBundle: Boolean, position: Int) {
        recyclerView.scrollToPosition(position)
        AppExecutor.uiExecutor.executeWithDelay({
            val viewHolder = recyclerView.findViewHolderForAdapterPosition(position)
            viewHolder?.itemView?.performClick()
            if (isResetBundle) {
                mParentBundle?.putString(EntranceConsts.KEY_PLATFORM, "")
                mParentBundle?.putString(EntranceConsts.KEY_PACKAGENAME, "")
            }
            mParentBundle?.putBoolean(EntranceConsts.KEY_PLATFORMS_AUTO_DOWNLOAD, false)
        }, 200)
    }

    @SuppressLint("ClickableViewAccessibility")
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
        mBinding = DialogDownloadBinding.bind(layoutInflater.inflate(R.layout.dialog_download, container, false))
        mBinding.title.text = ("选择下载" + mGameEntity.pluginDesc + "版本")

        val downloadNotice = mGameEntity.downloadAd
        if (downloadNotice != null) {
            mBinding.downloadNotice.visibility = View.VISIBLE
            mBinding.downloadNotice.text = downloadNotice.title
            mBinding.downloadNotice.setOnClickListener {
                if ("imprint" == downloadNotice.type) {
                    DialogUtils.showImprintDialog(requireContext(), mGameEntity, downloadNotice.title)
                } else {
                    DirectUtils.directToLinkPage(
                        requireContext(),
                        downloadNotice,
                        mEntrance, "下载多平台弹窗"
                    )
                }
//                MtaHelper.onEvent(MTA_KEY, "点击", mViewModel.gameEntity.name + "_" + downloadNotice.title)
            }
        }

        mBinding.back.setOnClickListener {
            if (mCollectionAdapter != null && mAdapter != null) {
                postBrowseMta()
                mViewModel.collectionLiveData.postValue(null)
            } else {
                dismissAllowingStateLoss()
            }
        }
        mBinding.back.setOnTouchListener(this)
        mBinding.downloadNotice.setOnTouchListener(this)

        (mBinding.contentList.itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
        (mBinding.collectionList.itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
        mBinding.contentList.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                val layoutManager = mBinding.contentList.layoutManager
                if (layoutManager is LinearLayoutManager) {
                    val position = layoutManager.findLastVisibleItemPosition()
                    mBinding.otherVersionButtonContainer.goneIf(position > mViewModel.otherSectionPosition - 1)
                }
            }
        })

        val smoothScroller: SmoothScroller = object : LinearSmoothScroller(requireContext()) {
            override fun getVerticalSnapPreference(): Int {
                return SNAP_TO_START
            }
        }
        mBinding.otherVersionButtonContainer.setOnClickListener {
            smoothScroller.targetPosition = mViewModel.otherSectionPosition
            mBinding.contentList.layoutManager?.startSmoothScroll(smoothScroller)
        }
        return mBinding.root
    }

    private fun collectionEnterAnimation() {
        val backAnimation = AnimationUtils.loadAnimation(requireContext(), R.anim.download_dialog_collection_back_enter)
        backAnimation.fillAfter = true
        mBinding.back.startAnimation(backAnimation)

        val contentAnimation = AnimationUtils.loadAnimation(requireContext(), R.anim.download_dialog_content_enter)
        contentAnimation.setAnimationListener(object : Animation.AnimationListener {
            override fun onAnimationRepeat(animation: Animation?) {
            }

            override fun onAnimationEnd(animation: Animation?) {
                mBinding.contentListContainer.visibility = View.GONE
            }

            override fun onAnimationStart(animation: Animation?) {
            }
        })
        mBinding.contentListContainer.startAnimation(contentAnimation)

        val collectionAnimation =
            AnimationUtils.loadAnimation(requireContext(), R.anim.download_dialog_collection_content_enter)
        mBinding.collectionList.startAnimation(collectionAnimation)
        mBinding.collectionList.visibility = View.VISIBLE
    }

    private fun collectionExitAnimation() {
        val backAnimation = AnimationUtils.loadAnimation(requireContext(), R.anim.download_dialog_collection_back_exit)
        backAnimation.fillAfter = true
        mBinding.back.startAnimation(backAnimation)

        val contentAnimation = AnimationUtils.loadAnimation(requireContext(), R.anim.download_dialog_content_exit)
        mBinding.contentListContainer.startAnimation(contentAnimation)
        mBinding.contentListContainer.visibility = View.VISIBLE

        val collectionAnimation =
            AnimationUtils.loadAnimation(requireContext(), R.anim.download_dialog_collection_content_exit)
        collectionAnimation.setAnimationListener(object : Animation.AnimationListener {
            override fun onAnimationRepeat(animation: Animation?) {
            }

            override fun onAnimationEnd(animation: Animation?) {
                mBinding.collectionList.visibility = View.GONE
            }

            override fun onAnimationStart(animation: Animation?) {
            }
        })
        mBinding.collectionList.startAnimation(collectionAnimation)
    }

    private fun createLayoutManager(listData: List<DownloadDialogItemData>): RecyclerView.LayoutManager {
        val layoutManager = GridLayoutManager(requireContext(), 2)
        layoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
            override fun getSpanSize(position: Int): Int {
                return if (listData[position].normal == null) 2 else 1
            }
        }
        return layoutManager
    }

    override fun onResume() {
        mAdapter?.notifyDataSetChanged()
        mCollectionAdapter?.notifyDataSetChanged()
        super.onResume()
        DownloadManager.getInstance().addObserver(mDataWatcher)
        mElapsedHelper.resetCounting()
        mElapsedHelper.resumeCounting()
    }

    override fun onPause() {
        super.onPause()
        DownloadManager.getInstance().removeObserver(mDataWatcher)
        mElapsedHelper.pauseCounting()
        postBrowseMta()
    }

    private fun postBrowseMta() {
//        if (mCollectionAdapter == null) {
//            MtaHelper.onEventWithTime(MTA_KEY, mElapsedHelper.elapsedTime, "浏览", mGameEntity?.name)
//        } else {
//            val collectionData = mViewModel.collectionLiveData.value
//            MtaHelper.onEventWithTime(MTA_KEY, mElapsedHelper.elapsedTime, "浏览", mGameEntity?.name + "_" + collectionData?.name)
//            throwExceptionInDebug("collectionData must be not null", collectionData == null)
//        }
    }

    override fun onBack(): Boolean {
        if (mCollectionAdapter != null && mAdapter != null) {
            postBrowseMta()
            mViewModel.collectionLiveData.postValue(null)
            return true
        }
        return super.onBack()
    }


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

    //安装、卸载事件
    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onEventMainThread(busFour: EBPackage) {
        if (::mViewModel.isInitialized && mViewModel.gameEntity.pluggableCollection == null) {
            val listData = mViewModel.listLiveData.value ?: return
            listData.forEach { itemData ->
                if (itemData.installed != null) {
                    if (itemData.installed?.packageName == busFour.packageName) {
                        mViewModel.initListData()
                        return
                    }
                }

                if (itemData.normal != null) {
                    if (itemData.normal?.packageName == busFour.packageName) {
                        mViewModel.initListData()
                        return
                    }
                }
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        EventBus.getDefault().unregister(this)
    }

    companion object {

        @JvmStatic
        fun showDownloadDialog(
            context: Context?,
            gameEntity: GameEntity,
            traceEvent: ExposureEvent?,
            entrance: String?,
            location: String?,
            onDownloadClickAction: ((Boolean) -> Unit)? = null
        ) {
            val fragmentActivity: FragmentActivity = if (context is FragmentActivity) {
                context
            } else if (BuildConfig.DEBUG) {
                throw IllegalStateException("DownloadDialog context must be FragmentActivity")
            } else {
                val currentActivity = AppManager.getInstance().currentActivity()
                if (currentActivity is FragmentActivity) {
                    currentActivity
                } else {
                    throw IllegalStateException("current activity context must be FragmentActivity")
                }
            }

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

            val downloadDialog = DownloadDialog().apply {
                val bundle = Bundle()
                bundle.putString(EntranceConsts.KEY_ENTRANCE, entrance)
                bundle.putString(EntranceConsts.KEY_LOCATION, location)
                bundle.putParcelable(GameEntity::class.java.simpleName, gameEntity)
                bundle.putParcelable(EntranceConsts.KEY_TRACE_EVENT, traceEvent)
                arguments = bundle
            }
            downloadDialog.onDownloadClickAction = onDownloadClickAction
            downloadDialog.show(fragmentActivity.supportFragmentManager, DownloadDialog::class.java.name)
        }

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

        const val MTA_KEY = "多版本下载"
    }
}