package com.gh.common.dialog

import android.app.Dialog
import android.content.Context
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Message
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import com.facebook.drawee.view.SimpleDraweeView
import com.gh.download.DownloadManager
import com.gh.gamecenter.R
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.utils.ImageUtils
import com.gh.gamecenter.common.utils.countDownTimer
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.core.utils.GsonUtils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.databinding.DialogDeviceRemindBinding
import com.gh.gamecenter.entity.DeviceDialogEntity
import com.gh.gamecenter.feature.entity.GameEntity
import com.google.gson.reflect.TypeToken
import com.lightgame.download.DataWatcher
import com.lightgame.download.DownloadEntity
import com.lightgame.download.DownloadStatus
import io.reactivex.disposables.Disposable
import java.lang.ref.WeakReference

/**
 * 设备提醒弹窗
 */
class DeviceRemindDialog(context: Context, val entity: DeviceDialogEntity, val gameEntity: GameEntity) :
    Dialog(context, com.gh.gamecenter.common.R.style.GhAlertDialog) {
    private val mBinding: DialogDeviceRemindBinding by lazy { DialogDeviceRemindBinding.inflate(layoutInflater) }
    private var currentPage = 0
    private var mSlideLooperInterval = 3000L
    private lateinit var mLooperHandle: LooperHandle
    private lateinit var mAdapter: BannerAdapter
    private var mDatas: ArrayList<String> = ArrayList()
    private val mSlideLooperKey = 100
    private var disposable: Disposable? = null
    private val dataWatcher = object : DataWatcher() {
        override fun onDataChanged(downloadEntity: DownloadEntity) {
            if (downloadEntity.status == DownloadStatus.done && downloadEntity.name == gameEntity.name) {
                val autoInstall = SPUtils.getBoolean(Constants.SP_AUTO_INSTALL, true)
                if (autoInstall) {
                    dismiss()
                }
            }
        }
    }

    companion object {
        fun showDeviceRemindDialog(context: Context, gameEntity: GameEntity) {
            val datas = SPUtils.getString(Constants.SP_DEVICE_REMIND)
            if (datas.isNotEmpty()) {
                val pair = shouldShowDeviceRemindDialog(gameEntity)
                if (pair.first) {
                    val dialog = DeviceRemindDialog(context, pair.second!!, gameEntity)
                    dialog.show()
                }
            }
        }

        fun shouldShowDeviceRemindDialog(gameEntity: GameEntity): Pair<Boolean, DeviceDialogEntity?> {
            val datas = SPUtils.getString(Constants.SP_DEVICE_REMIND)
            if (datas.isNotEmpty()) {
                val type = object : TypeToken<List<DeviceDialogEntity>>() {}.type
                val entities = GsonUtils.gson.fromJson<List<DeviceDialogEntity>>(datas, type)
                //1.判断设备是否匹配
                val entity =
                    entities.find { it.manufacturer.toLowerCase().startsWith(Build.MANUFACTURER.toLowerCase()) }
                        ?: return Pair(false, null)
                //2.判断游戏不含剔除标签
                gameEntity.tagStyle.forEach {
                    if (entity.excludeTags.contains(it.name)) {
                        return Pair(false, null)
                    }
                }
                //3.不再弹出提示判断
                val isNoRemindAgain = SPUtils.getBoolean(Constants.SP_NO_REMIND_AGAIN, false)
                if (isNoRemindAgain) return Pair(false, null)
                return Pair(true, entity)
            }
            return Pair(false, null)
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
        setContentView(mBinding.root)
        mDatas.addAll(entity.gallery)
        mBinding.titleTv.text = entity.title
        mBinding.contentTv.text = entity.content

        mBinding.bannerView.apply {
            orientation = ViewPager2.ORIENTATION_HORIZONTAL
            mAdapter = BannerAdapter()
            val recyclerView = getChildAt(0) as RecyclerView
            recyclerView.overScrollMode = RecyclerView.OVER_SCROLL_NEVER
            registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
                override fun onPageSelected(position: Int) {
                    super.onPageSelected(position)
                    currentPage = position
                    slideIndicator(currentPage % mDatas.size)
                }
            })
            recyclerView.addOnItemTouchListener(object : RecyclerView.SimpleOnItemTouchListener() {
                override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
                    val isStop = e.action == MotionEvent.ACTION_DOWN || e.action == MotionEvent.ACTION_MOVE
                    if (isStop) mAdapter.stopScroll() else mAdapter.startScroll()
                    return false
                }
            })
            adapter = mAdapter
            mLooperHandle = LooperHandle(mAdapter)
            currentPage = (adapter as BannerAdapter).getActualFirstPositionInCenter()
            setCurrentItem(currentPage, false)
            if (mDatas.size > 1) {
                addIndicator()
                slideIndicator(currentPage % mDatas.size)
                autoPlay()
            }
        }
        val isFirst = SPUtils.getBoolean(Constants.SP_FIRST_DEVICE_REMIND, false)
        if (!isFirst) {
            mBinding.cancelTv.isEnabled = false
            mBinding.cancelTv.background = ContextCompat.getDrawable(context, com.gh.gamecenter.common.R.drawable.button_round_f5f5f5)
            disposable = countDownTimer(3) { finish, time ->
                if (finish) {
                    mBinding.cancelTv.isEnabled = true
                    mBinding.cancelTv.background = ContextCompat.getDrawable(context, com.gh.gamecenter.common.R.drawable.button_blue_oval)
                    mBinding.cancelTv.text = "我知道了"
                    mBinding.cancelTv.setTextColor(ContextCompat.getColor(context, com.gh.gamecenter.common.R.color.white))
                } else {
                    mBinding.cancelTv.text = "我知道了(${time}S)"
                }
            }

            SPUtils.setBoolean(Constants.SP_FIRST_DEVICE_REMIND, true)
        } else {
            mBinding.noRemindAgainCb.visibility = View.VISIBLE
            mBinding.cancelTv.text = "我知道了"
            mBinding.cancelTv.isEnabled = true
            mBinding.cancelTv.setTextColor(ContextCompat.getColor(context, com.gh.gamecenter.common.R.color.white))
            mBinding.cancelTv.background = ContextCompat.getDrawable(context, com.gh.gamecenter.common.R.drawable.button_blue_oval)
        }
        mBinding.cancelTv.setOnClickListener {
            SPUtils.setBoolean(Constants.SP_NO_REMIND_AGAIN, mBinding.noRemindAgainCb.isChecked)
            dismiss()
        }
        DownloadManager.getInstance().addObserver(dataWatcher)
    }

    private fun addIndicator() {
        mBinding.indicatorLl.removeAllViews()
        mDatas.forEach { _ ->
            val indicatorView = ImageView(context).apply {
                setImageResource(R.drawable.selector_device_remind_indicator)
                val params = LinearLayout.LayoutParams(DisplayUtils.dip2px(8F), LinearLayout.LayoutParams.WRAP_CONTENT)
                params.leftMargin = DisplayUtils.dip2px(1F)
                params.rightMargin = DisplayUtils.dip2px(1F)
                layoutParams = params
            }
            mBinding.indicatorLl.addView(indicatorView)
        }
    }

    private fun slideIndicator(position: Int) {
        for (i in 0 until mBinding.indicatorLl.childCount) {
            val childAt = mBinding.indicatorLl.getChildAt(i)
            childAt.isSelected = i == position
        }
    }

    private fun autoPlay() {
        mAdapter.startScroll()
    }

    inner class BannerAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
            return object : RecyclerView.ViewHolder(
                LayoutInflater.from(context).inflate(R.layout.item_device_remind_banner, parent, false)
            ) {}
        }

        override fun getItemCount(): Int = if (mDatas.size == 1) mDatas.size else Int.MAX_VALUE

        override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
            val data = mDatas[position % mDatas.size]
            val view = holder.itemView as SimpleDraweeView
            ImageUtils.display(view, data)
        }

        fun getActualFirstPositionInCenter(): Int {
            if (mDatas.size == 1) return 0
            var index = itemCount / 2
            if (index % mDatas.size != 0) {
                index -= (index % mDatas.size)
            }
            return index
        }

        fun scrollToNextPage() {
            currentPage++
            mBinding.bannerView.setCurrentItem(currentPage, true)
        }

        fun startScroll() {
            mLooperHandle.removeMessages(mSlideLooperKey)
            mLooperHandle.sendEmptyMessageDelayed(mSlideLooperKey, mSlideLooperInterval)
        }

        fun stopScroll() {
            mLooperHandle.removeMessages(mSlideLooperKey)
        }
    }

    class LooperHandle(val mAdapter: BannerAdapter) : Handler() {
        private val mWeakReference: WeakReference<BannerAdapter> = WeakReference(mAdapter)
        override fun handleMessage(msg: Message) {
            val adapter = mWeakReference.get()
            adapter?.scrollToNextPage()
            adapter?.startScroll()
        }
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        if (disposable != null && !disposable!!.isDisposed) {
            disposable!!.dispose()
            disposable = null
        }
        DownloadManager.getInstance().removeObserver(dataWatcher)
    }
}