package com.gh.gamecenter.vote

import android.app.Dialog
import android.content.Intent
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.text.TextUtils
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.View
import android.view.Window
import android.view.inputmethod.EditorInfo
import android.widget.TextView
import androidx.core.widget.addTextChangedListener
import androidx.recyclerview.widget.RecyclerView
import com.gh.common.constant.Config
import com.gh.common.exposure.ExposureListener
import com.gh.common.util.*
import com.gh.common.util.DialogUtils
import com.gh.common.util.DirectUtils.directToLinkPage
import com.gh.gamecenter.R
import com.gh.gamecenter.common.baselist.ListFragment
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.utils.MtaHelper.onEvent
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.databinding.DialogAddVoteBinding
import com.gh.gamecenter.databinding.FragmentVoteBinding
import com.gh.gamecenter.feature.entity.InstallGameEntity
import com.gh.gamecenter.entity.VersionVoteEntity
import com.gh.gamecenter.game.upload.GameUploadFragment
import com.gh.gamecenter.game.upload.UploadScheduleDialog
import com.lightgame.utils.Util_System_Keyboard
import io.reactivex.disposables.Disposable
import org.json.JSONObject
import java.io.File
import java.util.*

class VoteFragment : ListFragment<VersionVoteEntity, VoteViewModel>() {
    private lateinit var mBinding: FragmentVoteBinding
    private lateinit var mAdapter: VoteAdapter
    private lateinit var mUploadDialog: UploadScheduleDialog
    private var mDisposable: Disposable? = null
    private var mUploadFileDisposable: Disposable? = null
    private lateinit var mExposureListener: ExposureListener

    private var mGameId = ""
    private var mApkUrl = ""

    override fun getLayoutId() = 0

    override fun getInflatedLayout() = FragmentVoteBinding.inflate(layoutInflater).apply { mBinding = this }.root

    override fun provideListAdapter() =
        if (!::mAdapter.isInitialized) VoteAdapter(requireContext(), this,
            { ifLogin("下载游戏-求版本-[添加选项]") { showAddVoteDialog() } },
            {
                ifLogin("下载游戏-求版本-[投票]") {
                    if (it != null) {
                        postVersionVote(it.trim(), false)
                    } // 投票
                }
            }).also {
            mAdapter = it
        } else mAdapter

    override fun provideListViewModel(): VoteViewModel = viewModelProvider(VoteViewModel.Factory(mGameId))

    override fun getItemDecoration(): RecyclerView.ItemDecoration? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        mGameId = requireArguments().getString(EntranceConsts.KEY_GAMEID) ?: ""
        setNavigationTitle(
            getString(
                R.string.title_vote_formatable,
                requireArguments().getString(EntranceConsts.KEY_GAMENAME)
            )
        )
        super.onCreate(savedInstanceState)
        initAd()
        initSearchBar()
        mBinding.reuseNoneData.reuseResetLoadTv.visibility = View.VISIBLE
        mBinding.reuseNoneData.reuseResetLoadTv.text = getString(R.string.vote_add)
        mBinding.reuseNoneData.reuseResetLoadTv.setOnClickListener {
            ifLogin("下载游戏-求版本-[添加选项]") { showAddVoteDialog() }
        }
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        mExposureListener = ExposureListener(this, mAdapter)
        mListRv?.addOnScrollListener(mExposureListener)
        mListViewModel.uploadSuccess.observe(viewLifecycleOwner) {
            if (it) {
                mUploadDialog.updateProgress(360) // 上传完APK就到100%
                mUploadDialog.dismiss()
                mAdapter.updateDataWhenUploadSuccess()
                mApkUrl = ""
                toast("上传成功，正在加急制作中~")
            } else {
                mUploadDialog.uploadFail()
            }
        }
    }

    private fun initAd() {
        val ad = AdHelper.getAd(AdHelper.LOCATION_GAME_REQUEST_VERSION)
        if (ad != null) {
            mBinding.tvAd.visibility = View.VISIBLE
            mBinding.tvAd.text = ad.title
            mBinding.tvAd.setOnClickListener {
                onEvent("广告位统计", "游戏下载求版本", ad.title)
                directToLinkPage(requireContext(), ad.toLinkEntity(), "(游戏下载求版本-广告位)", "")
            }
        }
    }

    private fun initSearchBar() {
        mBinding.searchBarInclude.run {
            root.setPadding(16F.dip2px(), 8F.dip2px(), 16F.dip2px(), 8F.dip2px())
            tvBack.visibility = View.GONE
            etSearch.hint = "输入搜索关键词"
            etSearch.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? ->
                if (actionId == EditorInfo.IME_ACTION_SEARCH) {
                    tvSearch.performClick()
                }
                false
            }
            etSearch.addTextChangedListener { s ->
                tvBack.visibility = if (s.isNullOrEmpty()) View.GONE else View.VISIBLE
            }
            tvSearch.setOnClickListener {
                if (etSearch.text.isNullOrEmpty()) {
                    toast("请输入搜索关键词")
                } else {
                    mListViewModel.searchVersion(etSearch.text.trim().toString())
                    Util_System_Keyboard.hideSoftKeyboard(requireContext(), etSearch)
                }
            }
            tvBack.setOnClickListener {
                etSearch.text.clear()
                mListViewModel.searchVersion("")
            }
        }
    }

    override fun loadDone(obj: Any?) {
        if (obj is String) {
            CheckLoginUtils.checkLogin(requireContext(), "下载游戏-求版本-[投票]") {
                postVersionVote(obj.toString().trim(), false) // 投票
            }
        }
        if (obj is InstallGameEntity) {
            mAdapter.mSelectGameDialog?.dismiss()
            if (!::mUploadDialog.isInitialized) {
                mUploadDialog = UploadScheduleDialog()
            }
            mUploadDialog.onClickListener = getUploadClickListener(obj)
            mUploadDialog.show(childFragmentManager, "upload")
            uploadApk(obj)
        }
    }

    private fun getUploadClickListener(entity: InstallGameEntity): (pos: Int) -> Unit {
        return {
            when (it) {
                0 -> {
                    //暂停上传
                    mDisposable?.dispose()
                    mUploadFileDisposable?.dispose()
                    mUploadDialog.isDisable = true

                    DialogHelper.showDialog(requireContext(), "提示",
                        "游戏上传中，确定要退出上传吗？", "不了", "确定", {
                            mUploadDialog.isDisable = false
                            if (mApkUrl.isEmpty()) {
                                uploadApk(entity)
                            } else {
                                mListViewModel.postApkInfo(mApkUrl, entity)
                            }
                        }, {
                            mUploadDialog.dismiss()
                        }, extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true)
                    )
                }
                1 -> {
                    mUploadDialog.dismiss()
                }
                2 -> {
                    DirectUtils.directToQqConversation(requireContext(), qqNumber = Config.getSettings()?.support?.qq)
                }
            }
        }
    }

    //上传apk
    private fun uploadApk(installGameEntity: InstallGameEntity) {
        val path = installGameEntity.gamePath ?: ""
        mUploadFileDisposable = OssUploadUtils.uploadFile(
            path,
            OssUploadUtils.UploadType.GAME,
            object : OssUploadUtils.OnUploadFileListener {
                override fun onSuccess(url: String) {
                    mApkUrl = url
                    mUploadFileDisposable?.dispose()
                    mUploadDialog.updateProgress(357) //即99%
                    mListViewModel.postApkInfo(mApkUrl, installGameEntity)
                }

                override fun onError(e: Throwable?) {
                    mUploadDialog.uploadFail()
                }
            }, { _, currentSize, totalSize ->
                val progress = (currentSize / totalSize.toFloat()) * 357 //即最多99%
                mUploadDialog.updateProgress(progress.toInt())
            })
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (data == null) return
        if (requestCode == GameUploadFragment.CHOOSE_LOCAL_APK) {
            val packageName = data.getStringExtra(EntranceConsts.KEY_PACKAGENAME) ?: ""
            val gamePath = data.getStringExtra(EntranceConsts.KEY_PATH) ?: ""
            val version = PackageUtils.getVersionNameByPackageName(packageName)
            val versionCode = data.getIntExtra(EntranceConsts.KEY_VERSION_CODE, 0)
            val format = data.getStringExtra(EntranceConsts.KEY_FORMAT) ?: ""
            val id = data.getStringExtra(EntranceConsts.KEY_PLATFORM_REQUESTS_ID) ?: ""
            val length = File(gamePath).length()
            if (length > 5 * 1024 * 1024 * 1024) {
                ToastUtils.showToast(getString(R.string.apk_max_size_hint, 5))
                return
            }
            loadDone(InstallGameEntity().apply {
                this.packageName = packageName
                this.gameSize = length
                this.gamePath = gamePath
                this.gameVersion = version
                this.versionCode = versionCode
                this.format = format
                this.platformRequestsId = id
            })
        }
    }

    private fun showAddVoteDialog() {
        val dialog = Dialog(requireContext())
        val binding = DialogAddVoteBinding.inflate(LayoutInflater.from(requireContext()))
        binding.confirmTv.setOnClickListener {
            val nickname = binding.contentEt.text.toString().trim { it <= ' ' }
            if (TextUtils.isEmpty(nickname)) {
                toast(R.string.vote_empty_hint)
                return@setOnClickListener
            }
            postVersionVote(nickname.trim(), true)
            dialog.dismiss()
        }
        binding.cancelTv.setOnClickListener {
            dialog.dismiss()
        }
        binding.contentEt.addTextChangedListener { s ->
            binding.confirmTv.isEnabled = !s.isNullOrEmpty()
            binding.confirmTv.alpha = if (s.isNullOrEmpty()) 0.4F else 1F
        }
        binding.contentEt.setOnEditorActionListener { _: TextView?, actionId: Int, _: KeyEvent? ->
            if (actionId == EditorInfo.IME_ACTION_DONE) {
                val nickname = binding.contentEt.text.toString().trim { it <= ' ' }
                if (TextUtils.isEmpty(nickname)) {
                    toast(R.string.vote_empty_hint)
                    return@setOnEditorActionListener true
                }
                postVersionVote(nickname.trim(), true)
                dialog.dismiss()
                return@setOnEditorActionListener true
            }
            false
        }

        dialog.setOnDismissListener {
            Util_System_Keyboard.hideSoftKeyboard(requireActivity())
        }
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
        dialog.setContentView(binding.root)
        dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
        dialog.show()
        mCachedView.postDelayed({
            Util_System_Keyboard.showSoftKeyboard(
                context,
                binding.contentEt
            )
        }, 300)
    }

    private fun postVersionVote(name: String, isNewVote: Boolean) {
        if (isNewVote) {
            mAdapter.getDataList()?.forEach { voteEntity ->
                if (name == voteEntity?.name) {
                    val userDataEntity = voteEntity.me
                    if (userDataEntity != null && userDataEntity.isVersionRequested) {
                        toast(R.string.vote_success)
                        return
                    }
                }
            }
        }
        val waitDialog = DialogUtils.showWaitDialog(
            requireContext(),
            getString(R.string.vote_post)
        )
        mListViewModel.postVersionVote(name, isNewVote, { response ->
            try {
                waitDialog.dismiss()
                if (isNewVote) {
                    val id = JSONObject(response.string()).getString("_id")
                    toast(R.string.vote_success)
                    if (!TextUtils.isEmpty(id)) {
                        mAdapter.updateVote(isNewVote, id, name)
                        val lastView = mLayoutManager.findViewByPosition(mAdapter.itemCount - 1)
                        if (lastView != null) {
                            mBinding.scrollView.smoothScrollTo(0, lastView.top)
                        }
                    }
                } else {
                    mAdapter.updateVote(isNewVote, name, null)
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }, { e ->
            waitDialog.dismiss()
            if (e.code() == 403) {
                try {
                    val string = e.response().errorBody()!!.string()
                    val errorJson = JSONObject(string)
                    val detail = errorJson.getString("detail")
                    if ("illegal" == detail.lowercase(Locale.getDefault())) {
                        toast(R.string.vote_illegal_hint)
                    } else if ("already has" == detail.lowercase(Locale.getDefault()) && isNewVote) {
                        // 高亮
                        mAdapter.getDataList()?.forEachIndexed { index, entity ->
                            if (entity?.name == name) {
                                mAdapter.updateHighLightView(entity, index)
                                val highLightView = mLayoutManager.findViewByPosition(index)
                                if (highLightView != null) {
                                    mBinding.scrollView.smoothScrollTo(0, highLightView.top)
                                }
                                return@forEachIndexed
                            }
                        }
                        toast("已经存在相同的选项")
                    }
                } catch (e1: Exception) {
                    e1.printStackTrace()
                }
            } else {
                toast(R.string.post_failure_hint)
            }
        })
    }

    override fun onBackPressed(): Boolean {
        return if (mListViewModel.mKeyword.isNotEmpty()) {
            mBinding.searchBarInclude.tvBack.performClick()
            true
        } else {
            false
        }
    }
}