package com.gh.gamecenter.gamecollection.choose

import android.app.Dialog
import android.content.Context
import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
import android.widget.PopupWindow
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.widget.doAfterTextChanged
import androidx.core.widget.doOnTextChanged
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentTransaction
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.R
import com.gh.gamecenter.common.HaloApp
import com.gh.gamecenter.common.base.fragment.BaseDialogFragment
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.utils.DialogHelper
import com.gh.gamecenter.common.utils.goneIf
import com.gh.gamecenter.common.utils.viewModelProvider
import com.gh.gamecenter.common.view.BugFixedPopupWindow
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.databinding.DialogAddGamesBinding
import com.gh.gamecenter.databinding.LayoutGameCollectionAddGamesGuideBinding
import com.gh.gamecenter.feature.entity.GameEntity
import com.lightgame.utils.AppManager
import com.lightgame.utils.Util_System_Keyboard


class AddGamesDialogFragment : BaseDialogFragment() {
    private val binding by lazy { DialogAddGamesBinding.inflate(layoutInflater) }
    private var defaultFragment: Fragment? = null
    private var searchFragment: Fragment? = null
    private val chooseGamesViewModel: ChooseGamesViewModel by lazy { viewModelProvider(ChooseGamesViewModel.Factory()) }
    private var chooseGamesTemp: ArrayList<GameEntity> = arrayListOf()
    private var popupWindow: PopupWindow? = null

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        val createDialog = super.onCreateDialog(savedInstanceState)
        createDialog.setCanceledOnTouchOutside(true)

        val window = createDialog.window
        window?.setGravity(Gravity.TOP)
        window?.setWindowAnimations(com.gh.gamecenter.common.R.style.community_publication_animation)
        return createDialog
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        changeFragment(true)
    }

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

    override fun onStart() {
        super.onStart()
        val width = HaloApp.getInstance().resources.displayMetrics.widthPixels
        val height = dialog?.window?.attributes?.height ?: ViewGroup.LayoutParams.WRAP_CONTENT
        dialog?.window?.setLayout(width, height)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        chooseGamesTemp.clear()
        chooseGamesTemp.addAll(chooseGamesViewModel.chooseGamesLiveData.value ?: arrayListOf())
        binding.searchInput.doOnTextChanged { text, _, _, _ -> binding.searchBack.goneIf(text?.length == 0) }
        binding.searchInput.doAfterTextChanged { editable ->
            changeFragment(editable.isNullOrEmpty())
        }
        binding.searchInput.setOnEditorActionListener { _, actionId, _ ->
            if (actionId == EditorInfo.IME_ACTION_SEARCH) {
                Util_System_Keyboard.hideSoftKeyboard(requireActivity())
                search(true)
            }
            false
        }
        binding.searchBack.setOnClickListener {
            binding.searchBack.visibility = View.GONE
            binding.searchInput.setText("")
        }
        binding.searchButton.setOnClickListener {
            Util_System_Keyboard.hideSoftKeyboard(requireActivity())
            search(true)
        }
        binding.root.setOnClickListener {
            binding.closeIv.performClick()
        }
        binding.closeIv.setOnClickListener {
            if (!onBack()) {
                dismissAllowingStateLoss()
            }
        }
        binding.saveTv.setOnClickListener {
            dismissAllowingStateLoss()
        }

        chooseGamesViewModel.chooseGamesLiveData.observe(viewLifecycleOwner) {
            binding.saveTv.text = "保存 (${it.size})"
        }

        binding.root.postDelayed({
            if (SPUtils.getBoolean(Constants.SP_SHOW_GAME_COLLECTION_ADD_GAMES_GUIDE, true)) {
                popupWindow = showGuidePopupWindow()
            }
        }, 500)
    }

    private fun changeFragment(default: Boolean) {
        val transaction = childFragmentManager.beginTransaction()
        hideFragments(transaction)
        if (default) {
            defaultFragment = alterFragment(transaction, NewAddGamesFragment::class.java, true)
        } else {
            searchFragment = alterFragment(transaction, NewAddSearchGameFragment::class.java, false)
        }
        transaction.commitAllowingStateLoss()
    }

    private fun hideFragments(transaction: FragmentTransaction) {
        val list = childFragmentManager.fragments
        for (fragment in list) {
            transaction.hide(fragment)
        }
    }

    private fun <T : Fragment> alterFragment(transaction: FragmentTransaction, cls: Class<T>, default: Boolean): T {
        val tag = cls.simpleName
        var fragmentByTag = childFragmentManager.findFragmentByTag(tag) as T?
        try {
            if (fragmentByTag != null) {
                transaction.show(fragmentByTag)
                search()
            } else {
                fragmentByTag = cls.newInstance()
                if (!default) {
                    val bundle = Bundle()
                    bundle.putString(EntranceConsts.KEY_SEARCHKEY, binding.searchInput.text.toString().trim())
                    fragmentByTag.arguments = bundle
                }
                transaction.add(R.id.contentContainer, fragmentByTag, tag)
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }

        return fragmentByTag!!
    }

    private fun search(isManual: Boolean = false) {
        val searchKey = binding.searchInput.text.toString().trim()
        if (searchKey.isEmpty() && isManual) {
            toast("请输入搜索内容")
        }
        if (searchKey.isNotEmpty() && searchFragment is NewAddSearchGameFragment) {
            (searchFragment as NewAddSearchGameFragment).updateSearchKey(searchKey)
        }
    }

    override fun onBack(): Boolean {
        if (popupWindow?.isShowing == true) {
            popupWindow?.dismiss()
            return true
        }

        val chooseGames = chooseGamesViewModel.chooseGamesLiveData.value
        if (!chooseGames.isNullOrEmpty() || chooseGamesTemp.isNotEmpty()) {
            DialogHelper.showDialog(requireContext(), "提示", "是否保存本次选择的游戏", "保存", "取消", {
                binding.saveTv.performClick()
            }, {
                chooseGamesViewModel.chooseGamesLiveData.postValue(chooseGamesTemp)
                dismissAllowingStateLoss()
            }, extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true))
            return true
        }
        return super.onBack()
    }

    private fun showGuidePopupWindow(): PopupWindow? {
        if (!isAdded) return null

        val guideBinding = LayoutGameCollectionAddGamesGuideBinding.inflate(layoutInflater)
        val popupWindow = BugFixedPopupWindow(
            guideBinding.root,
            ConstraintLayout.LayoutParams.MATCH_PARENT,
            ConstraintLayout.LayoutParams.MATCH_PARENT
        )
        guideBinding.guideContainer.setOnClickListener {
            popupWindow.dismiss()
        }
        return popupWindow.apply {
            isTouchable = true
            isFocusable = true
            isOutsideTouchable = true
            isClippingEnabled = false
            animationStyle = com.gh.gamecenter.common.R.style.popup_window_ease_in_and_out_anim_style
            setOnDismissListener {
                SPUtils.setBoolean(Constants.SP_SHOW_GAME_COLLECTION_ADD_GAMES_GUIDE, false)
                this@AddGamesDialogFragment.popupWindow = null
            }
            showAtLocation(binding.root, Gravity.TOP, 0, 0)
        }
    }

    companion object {
        @JvmStatic
        fun show(context: Context?) {
            val fragmentActivity: FragmentActivity = if (context is FragmentActivity) {
                context
            } else if (BuildConfig.DEBUG) {
                throw IllegalStateException("AddGamesDialogFragment 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 (hasDialogInCurrentActivity(fragmentActivity)) return

            val addGamesDialog = AddGamesDialogFragment().apply {
                val bundle = Bundle()
                arguments = bundle
            }
            addGamesDialog.show(fragmentActivity.supportFragmentManager, AddGamesDialogFragment::class.java.name)
        }

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