package com.gh.vspace

import android.app.Dialog
import android.app.DialogFragment
import android.app.FragmentManager
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.FragmentTransaction
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.recyclerview.widget.*
import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback
import androidx.viewpager2.widget.ViewPager2.PageTransformer
import com.gh.common.util.NewFlatLogUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.common.utils.ImageUtils
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.layoutInflater
import com.gh.gamecenter.common.utils.safelyGetInRelease
import com.gh.gamecenter.common.view.PageControllerAdapter
import com.gh.gamecenter.common.view.PageTransformerAdapter
import com.gh.gamecenter.common.view.ScrollEventListener
import com.gh.gamecenter.databinding.DialogVgameInstalledLaunchBinding
import com.gh.gamecenter.databinding.ItemVgameInstalledLaunchBinding
import com.gh.gamecenter.feature.entity.InstallGameEntity
import com.gh.vspace.Constants.LAUNCH_LOCATION_INSTALLED_LAUNCH_DIALOG
import com.lightgame.download.DownloadEntity


class VGameInstalledLaunchDialog : DialogFragment() {

    companion object {

        private const val DIALOG_WIDTH = 300F

        private const val VIEW_PAGER_WIDTH = 112F

        private const val VIEW_PAGER_HEIGHT = 96F

        private const val MIN_ITEM_SCALE_SIZE = 52F

        private const val MAX_ITEM_SCALE_SIZE = 72F

        private const val ITEM_SCALE_SIZE_INTERVAL = MAX_ITEM_SCALE_SIZE - MIN_ITEM_SCALE_SIZE

        private const val MIN_ITEM_SCALE_HORIZONTAL_MARGIN = 8F

        private const val MAX_ITEM_SCALE_HORIZONTAL_MARGIN = 20F

        private const val ITEM_SCALE_HORIZONTAL_MARGIN_INTERVAL =
            MAX_ITEM_SCALE_HORIZONTAL_MARGIN - MIN_ITEM_SCALE_HORIZONTAL_MARGIN

        private const val TAG = "VGameInstalledLaunchDialog"

        fun show(fragmentManager: FragmentManager, downloadEntity: DownloadEntity) {
            val installedGame = VHelper.getAllInstalledVGameEntity().firstOrNull {
                downloadEntity.gameId == it.gameId
            } ?: return
            val dialog = fragmentManager.findFragmentByTag(TAG) as VGameInstalledLaunchDialog?
            if (dialog != null) {
                dialog.addLaunchGame(installedGame)
            } else {
                VGameInstalledLaunchDialog().apply {
                    addLaunchGame(installedGame)
                    show(fragmentManager, TAG)
                }
            }
        }
    }

    private val installAdapter: VInstalledGameListAdapter by lazy { VInstalledGameListAdapter() }

    private var binding: DialogVgameInstalledLaunchBinding? = null

    private fun addLaunchGame(installGameEntity: InstallGameEntity) {
        val newInstalledList = (installAdapter.currentList + installGameEntity).sortedWith { o1, o2 ->
            (o1.installTime - o2.installTime).toInt()
        }
        installAdapter.submitList(newInstalledList)
    }

    @Deprecated("Deprecated in Java")
    override fun show(manager: FragmentManager?, tag: String?) {
        try {
            val clazz: Class<*> = DialogFragment::class.java
            val dismissed = clazz.getDeclaredField("mDismissed")
            dismissed.isAccessible = true
            dismissed[this] = false

            val shownByMe = clazz.getDeclaredField("mShownByMe")
            shownByMe.isAccessible = true
            shownByMe[this] = true
            val transaction = manager!!.beginTransaction()
            transaction.add(this, tag)
            transaction.commitAllowingStateLoss()
        } catch (e: Exception) {
            super.show(manager, tag)
            e.printStackTrace()
        }
    }

    @Deprecated("Deprecated in Java")
    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        return super.onCreateDialog(savedInstanceState).apply {
            window?.setBackgroundDrawable(ColorDrawable())
        }
    }

    @Deprecated("Deprecated in Java")
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
        return DialogVgameInstalledLaunchBinding.inflate(inflater, container, false)
            .also { binding = it }
            .root
    }

    @Deprecated("Deprecated in Java")
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        binding?.apply {
            rv.apply {
                val horizontalPadding = ((DIALOG_WIDTH - VIEW_PAGER_WIDTH) / 2).dip2px()
                setPadding(horizontalPadding, 0, horizontalPadding, 0)

                adapter = installAdapter.apply { setOnCommitCallback { updateGameDesc(it) } }

                layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)

                val snapHelper = VInstalledPagerSnapHelper().also {
                    it.attachToRecyclerView(this)
                }

                ScrollEventListener(this).also {
                    val pageTransformerAdapter =
                        PageTransformerAdapter(it.mLayoutManager, VInstalledGameItemTransformer())
                    val pageControllerAdapter = PageControllerAdapter(this, snapHelper, it)
                    it.registerOnPageChangeCallback(pageControllerAdapter)
                    it.registerOnPageChangeCallback(pageTransformerAdapter)
                    it.registerOnPageChangeCallback(object : OnPageChangeCallback() {
                        override fun onPageSelected(position: Int) {
                            val currentList = installAdapter.currentList
                            val item = currentList.safelyGetInRelease(position) ?: return
                            gameName.text = item.gameName
                        }
                    })

                    installAdapter.setOnItemClickListener { _, i ->
                        pageControllerAdapter.currentItem = i
                    }

                    installAdapter.registerAdapterDataObserver(pageControllerAdapter.currentItemDataSetChangeObserver)

                    launch.setOnClickListener { view ->
                        val currentItem = pageControllerAdapter.currentItem
                        val installedGame =
                            installAdapter.currentList.safelyGetInRelease(currentItem) ?: return@setOnClickListener
                        val vDownloadEntity =
                            VHelper.getVDownloadEntitySnapshot(installedGame.gameId, installedGame.packageName)
                                ?: return@setOnClickListener
                        VHelper.installOrLaunch(
                            context = view.context,
                            downloadEntity = vDownloadEntity,
                            location = LAUNCH_LOCATION_INSTALLED_LAUNCH_DIALOG
                        )
                        NewFlatLogUtils.logHaloFunInstalledLaunchDialogClick(
                            gameId = installedGame.gameId,
                            gameName = installedGame.gameName ?: "",
                            buttonType = "启动游戏"
                        )
                        dismissAllowingStateLoss()
                    }

                    addOnScrollListener(it)
                }

                updateGameDesc(installAdapter.currentList.size)
            }

            NewFlatLogUtils.logHaloFunInstalledLaunchDialogShow()
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        installAdapter.setOnCommitCallback(null)
    }

    private fun updateGameDesc(size: Int) {
        binding?.gameDesc?.text = if (size == 1) {
            getString(R.string.dialog_vgame_installed_launch_desc_1)
        } else {
            getString(R.string.dialog_vgame_installed_launch_desc_2, size)
        }
    }

    class VInstalledGameListAdapter: ListAdapter<InstallGameEntity, VInstalledGameItemViewHolder>(COMPARATOR) {

        companion object {
            private val COMPARATOR = object : DiffUtil.ItemCallback<InstallGameEntity>() {

                override fun areItemsTheSame(oldItem: InstallGameEntity, newItem: InstallGameEntity): Boolean {
                    return oldItem.gameId == newItem.gameId
                            && oldItem.gameName == newItem.gameName
                            && oldItem.packageName == newItem.packageName
                            && oldItem.gameIcon == newItem.gameIcon
                }

                override fun areContentsTheSame(oldItem: InstallGameEntity, newItem: InstallGameEntity): Boolean {
                    return oldItem.gameId == newItem.gameId
                            && oldItem.gameName == newItem.gameName
                            && oldItem.packageName == newItem.packageName
                            && oldItem.gameIcon == newItem.gameIcon
                }

            }
        }

        private var onCommitCallback: ((Int) -> Unit)? = null

        private var onItemClickListener: ((View, Int) -> Unit)? = null

        fun setOnItemClickListener(onItemClick: (View, Int) -> Unit) {
            this.onItemClickListener = onItemClick
        }

        fun setOnCommitCallback(onCommitCallback: ((Int) -> Unit)?) {
            this.onCommitCallback = onCommitCallback
        }

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VInstalledGameItemViewHolder =
            VInstalledGameItemViewHolder(
                ItemVgameInstalledLaunchBinding.inflate(
                    parent.layoutInflater,
                    parent,
                    false
                )
            )

        override fun onBindViewHolder(holder: VInstalledGameItemViewHolder, position: Int) {
            // 指定图片的宽高，否则会图片变得很模糊
            holder.binding.icon.setTag(ImageUtils.TAG_TARGET_WIDTH, MAX_ITEM_SCALE_SIZE.dip2px())
            holder.binding.icon.displayGameIcon(getItem(position).gameIcon, null)
            holder.binding.icon.setOnClickListener {
                onItemClickListener?.invoke(it, position)
            }
        }

        override fun submitList(list: List<InstallGameEntity>?) {
            super.submitList(list) {
                onCommitCallback?.invoke(itemCount)
            }
        }
    }

    class VInstalledGameItemViewHolder(val binding: ItemVgameInstalledLaunchBinding) :
        RecyclerView.ViewHolder(binding.root)

    class VInstalledGameItemTransformer : PageTransformer {

        override fun transformPage(page: View, position: Float) {
            // 水平外边距会随着焦点位置距离变化而变化，取值范围(8-20)DP
            val horizontalMargin: Int
            // 图标大小会随着焦点位置距离变化而变化，取值范围(52-72)DP
            val size = if (position == 0F) {// 处于焦点位置，保持最大值
                horizontalMargin = MAX_ITEM_SCALE_HORIZONTAL_MARGIN.dip2px()
                MAX_ITEM_SCALE_SIZE.dip2px()
            } else if (position > 0F && position < 1F) {// 处于焦点与非焦点位置之间(右侧)，动态计算大小
                horizontalMargin =
                    (ITEM_SCALE_HORIZONTAL_MARGIN_INTERVAL * (1 - position) + MIN_ITEM_SCALE_HORIZONTAL_MARGIN).dip2px()
                (ITEM_SCALE_SIZE_INTERVAL * (1 - position) + MIN_ITEM_SCALE_SIZE).dip2px()
            } else if (position > -1F && position < 0F) {// 处于焦点与非焦点位置之间(左侧)，动态计算大小
                horizontalMargin =
                    (ITEM_SCALE_HORIZONTAL_MARGIN_INTERVAL * (1 + position) + MIN_ITEM_SCALE_HORIZONTAL_MARGIN).dip2px()
                (ITEM_SCALE_SIZE_INTERVAL * (1 + position) + MIN_ITEM_SCALE_SIZE).dip2px()
            } else {// 处于非焦点位置，保持最小值
                horizontalMargin = MIN_ITEM_SCALE_HORIZONTAL_MARGIN.dip2px()
                MIN_ITEM_SCALE_SIZE.dip2px()
            }
            // 垂直外边距
            val verticalMargin = (VIEW_PAGER_HEIGHT.dip2px() - size) / 2

            page.layoutParams = (page.layoutParams as RecyclerView.LayoutParams).apply {
                width = size
                height = size
                leftMargin = horizontalMargin
                rightMargin = horizontalMargin
                topMargin = verticalMargin
                bottomMargin = verticalMargin
            }
        }
    }

    class VInstalledPagerSnapHelper : PagerSnapHelper() {

        override fun calculateDistanceToFinalSnap(
            layoutManager: RecyclerView.LayoutManager,
            targetView: View
        ): IntArray = intArrayOf(distanceToCenter(layoutManager, targetView), 0)

        private fun distanceToCenter(layoutManager: RecyclerView.LayoutManager, targetView: View): Int {
            val params = targetView.layoutParams as RecyclerView.LayoutParams
            val decoratedStart = layoutManager.getDecoratedLeft(targetView) - params.leftMargin
            // 与自带的PagerSnapHelper的区别在这里，移动的距离必须是图标的最大值，否则会onPageSelected会出现重复回调的问题
            val decoratedMeasurement = MAX_ITEM_SCALE_SIZE.dip2px() + params.leftMargin + params.rightMargin
            val childCenter = decoratedStart + decoratedMeasurement / 2

            val totalSpace = layoutManager.width - layoutManager.paddingLeft - layoutManager.paddingRight
            val startAfterPadding = layoutManager.paddingLeft
            val containerCenter = startAfterPadding + totalSpace / 2

            return childCenter - containerCenter
        }
    }
}