package com.gh.gamecenter.toolbox

import android.os.Bundle
import android.view.KeyEvent
import android.view.MotionEvent
import android.view.View
import android.view.inputmethod.EditorInfo
import android.widget.EditText
import android.widget.TextView
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.SimpleItemAnimator
import com.gh.gamecenter.R
import com.gh.gamecenter.WebActivity
import com.gh.gamecenter.common.base.fragment.ToolbarFragment
import com.gh.gamecenter.common.baselist.LoadStatus
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.entity.SuggestType
import com.gh.gamecenter.common.utils.TextHelper
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.observeNonNull
import com.gh.gamecenter.common.utils.toColor
import com.gh.gamecenter.common.view.CustomLinkMovementMethod
import com.gh.gamecenter.core.utils.SpanBuilder
import com.gh.gamecenter.databinding.FragmentToolboxBinding
import com.gh.gamecenter.help.HelpAndFeedbackBridge
import com.lightgame.utils.Util_System_Keyboard

class ToolboxFragment : ToolbarFragment() {
    private var mIsEverPause = false
    private val mBinding by lazy { FragmentToolboxBinding.inflate(layoutInflater) }
    private val mViewModel: ToolBoxViewModel by viewModels()
    private val mAdapter: ToolBoxBlockAdapter by lazy { ToolBoxBlockAdapter(requireContext(), mViewModel) }
    private val mSearchAdapter: ToolBoxItemAdapter by lazy { ToolBoxItemAdapter(requireContext(), false, mViewModel) }
    private val mLayoutManager: LinearLayoutManager by lazy { LinearLayoutManager(requireContext()) }

    private var mIsSearch = false  // 记录页面状态 搜索页面/普通页面

    override fun getLayoutId(): Int = 0
    override fun getInflatedLayout(): View = mBinding.root

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setNavigationTitle("光环工具箱")

        // 跳转到工具箱 https://gitlab.ghzs.com/pm/halo-app-issues/issues/636
        val gameId = arguments?.getString(EntranceConsts.KEY_GAMEID)
        val targetUrl = arguments?.getString(EntranceConsts.KEY_URL)
        if (!gameId.isNullOrEmpty() && !targetUrl.isNullOrEmpty()) {
            mViewModel.getGameToolBoxData(gameId) {
                for (toolbox in it) {
                    if (targetUrl == toolbox.url) {
                        mViewModel.addToHistoryList(toolbox)
                        startActivity(WebActivity.getWebByCollectionTools(requireContext(), toolbox, false))
                    }
                }
            }
        }

        mBinding.run {
            toolboxRefresh.setColorSchemeResources(com.gh.gamecenter.common.R.color.primary_theme)
            toolboxRefresh.setOnRefreshListener {
                refresh()
            }
            feedbackTv.text =
                SpanBuilder("需要其他工具，点击反馈").click(requireContext(), 7, 11, com.gh.gamecenter.common.R.color.primary_theme, false) {
                    HelpAndFeedbackBridge.startSuggestionActivity(
                        requireContext(),
                        SuggestType.UPDATE,
                        null,
                        null
                    )
                }.build()
            feedbackTv.movementMethod = CustomLinkMovementMethod.getInstance()
            closeIv.setOnClickListener { mBinding.feedbackCv.visibility = View.GONE }
            toolboxRv.adapter = mAdapter
            toolboxRv.layoutManager = mLayoutManager
            (toolboxRv.itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
            toolboxAppbar.addOnOffsetChangedListener { _, verticalOffset ->
                toolboxRefresh.isEnabled = verticalOffset == 0
            }
        }
        mViewModel.toolBoxBlockList.observeNonNull(this) { list ->
            mAdapter.setDataList(list)
        }
        mViewModel.searchResultList.observeNonNull(this) { list ->
            mSearchAdapter.setDataList(list, true)
        }
        mViewModel.loadStatus.observeNonNull(this) {
            when (it) {
                LoadStatus.INIT_LOADED -> loadDone()
                LoadStatus.INIT_EMPTY -> loadEmpty()
                LoadStatus.INIT_FAILED -> loadError()
                else -> {
                    //do nothing
                }
            }
        }
        mViewModel.searchStatus.observeNonNull(this) {
            when (it) {
                LoadStatus.INIT_LOADED -> loadDone()
                LoadStatus.INIT_EMPTY -> loadEmpty()
                LoadStatus.INIT_FAILED -> loadError()
                else -> {
                    //do nothing
                }
            }
        }

        initSearch()
        mViewModel.getToolBoxList()
    }

    override fun onPause() {
        super.onPause()
        mIsEverPause = true
    }

    override fun onResume() {
        super.onResume()
        if (!mIsSearch && mIsEverPause) mAdapter.setHistoryList(mViewModel.getHistoryList())
    }

    override fun loadDone() {
        mBinding.toolboxRv.visibility = View.VISIBLE
        mBinding.toolboxRefresh.isRefreshing = false
        mBinding.reuseNoneData.root.visibility = View.GONE
        mBinding.reuseNoConnection.root.visibility = View.GONE
        mBinding.reuseLoading.root.visibility = View.GONE
    }

    override fun loadError() {
        mBinding.toolboxRv.visibility = View.GONE
        mBinding.toolboxRefresh.isRefreshing = false
        mBinding.reuseNoneData.root.visibility = View.GONE
        mBinding.reuseNoConnection.root.visibility = View.VISIBLE
        mBinding.reuseLoading.root.visibility = View.GONE
        mBinding.reuseNoConnection.root.setOnClickListener {
            refresh()
            mBinding.reuseNoConnection.root.visibility = View.GONE
            mBinding.reuseLoading.root.visibility = View.VISIBLE
        }
    }

    override fun loadEmpty() {
        mBinding.toolboxRv.visibility = View.GONE
        mBinding.toolboxRefresh.isRefreshing = false
        mBinding.reuseNoneData.root.visibility = View.VISIBLE
        mBinding.reuseNoConnection.root.visibility = View.GONE
        mBinding.reuseLoading.root.visibility = View.GONE
        mBinding.reuseNoneData.reuseNoneDataTv.text =
            if (mIsSearch) "这儿还没有内容噢~" else resources.getString(com.gh.gamecenter.common.R.string.game_empty)
        mBinding.reuseNoneData.root.setOnClickListener {
            if (mIsSearch) HelpAndFeedbackBridge.startSuggestionActivity(
                requireContext(),
                SuggestType.UPDATE,
                null,
                null
            )
        }
    }

    private fun refresh() {
        if (mIsSearch) {
            mViewModel.getSearchResultList()
        } else {
            mViewModel.getToolBoxList()
        }
    }

    private fun search(isSearch: Boolean, searchKey: String) {
        if (mBinding.reuseNoneData.root.visibility == View.VISIBLE) {
            mBinding.reuseNoneData.root.visibility = View.GONE
        }
        mIsSearch = isSearch
        mViewModel.mSearchKey = searchKey
        changeAdapter(isSearch)
        if (isSearch) {
            mBinding.reuseLoading.root.visibility = View.VISIBLE
            mBinding.toolboxRv.visibility = View.GONE
            mViewModel.getSearchResultList()
        }
    }

    private fun initSearch() {
        val backTv = mBinding.reuseSearchBar.tvBack
        val searchTv = mBinding.reuseSearchBar.tvSearch
        val searchEt = mBinding.reuseSearchBar.etSearch
        mBinding.reuseSearchBar.root.setPadding(16F.dip2px(), 8F.dip2px(), 16F.dip2px(), 8F.dip2px())
        backTv.setOnClickListener { backToBlock() }
        TextHelper.limitTheLengthOfEditText(searchEt, 20) { toast("最多输入20字") }
        searchTv.setOnClickListener {
            if (searchEt.text.toString().isEmpty()) {
                toast(R.string.search_hint)
                return@setOnClickListener
            }
            Util_System_Keyboard.hideSoftKeyboard(requireContext(), searchEt)
            search(true, searchEt.text.toString())
        }
        searchEt.onFocusChangeListener = View.OnFocusChangeListener { _: View?, hasFocus: Boolean ->
            if (!hasFocus) {
                Util_System_Keyboard.hideSoftKeyboard(requireContext(), searchEt)
            }
        }
        searchEt.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? ->
            if (actionId == EditorInfo.IME_ACTION_SEARCH) {
                searchTv.performClick()
            }
            false
        }
    }

    private fun changeAdapter(isSearch: Boolean) {
        mBinding.toolboxRv.adapter = if (isSearch) mSearchAdapter else mAdapter
        mBinding.reuseSearchBar.tvBack.visibility = if (mIsSearch) View.VISIBLE else View.GONE
    }

    override fun onTouchEvent(ev: MotionEvent?) {
        if (ev?.action == MotionEvent.ACTION_DOWN) {
            val v = requireActivity().currentFocus
            if (isShouldHideKeyboard(v, ev)) {
                Util_System_Keyboard.hideSoftKeyboard(requireActivity())
            }
        }
    }

    private fun isShouldHideKeyboard(v: View?, event: MotionEvent): Boolean {
        if (v is EditText) {
            val l = intArrayOf(0, 0)
            v.getLocationInWindow(l)
            val left = l[0]
            val top = l[1]
            val bottom = top + v.getHeight()
            val right = left + v.getWidth()
            return (event.x <= left || event.x >= right || event.y <= top || event.y >= bottom)
        }
        return false
    }

    // 搜索页返回集合页
    private fun backToBlock() {
        search(false, "")
        mAdapter.setHistoryList(mViewModel.getHistoryList())
        mBinding.reuseSearchBar.etSearch.text.clear()
        loadDone()
    }

    override fun onBackPressed(): Boolean {
        return if (mIsSearch) {
            backToBlock()
            true
        } else {
            super.onBackPressed()
        }
    }

    override fun onDarkModeChanged() {
        super.onDarkModeChanged()
        mBinding.run {
            toolboxRv.adapter?.run { notifyItemRangeChanged(0, itemCount) }
            feedbackCv.setCardBackgroundColor(com.gh.gamecenter.common.R.color.ui_surface.toColor(requireContext()))
        }
    }
}