package com.gh.gamecenter.game.upload

import android.app.Dialog
import android.content.Intent
import android.os.Bundle
import android.provider.MediaStore
import android.text.*
import android.text.method.LinkMovementMethod
import android.text.style.ClickableSpan
import android.view.LayoutInflater
import android.view.View
import android.view.Window
import android.widget.EditText
import android.widget.ProgressBar
import android.widget.TextView
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.gh.gamecenter.common.callback.OnListClickListener
import com.gh.common.constant.Config
import com.gh.common.util.*
import com.gh.gamecenter.CleanApkActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.WebActivity
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.core.utils.*
import com.gh.gamecenter.databinding.FragmentGameUploadBinding
import com.gh.gamecenter.entity.InstallGameEntity
import com.gh.gamecenter.common.base.fragment.ToolbarFragment
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.suggest.SuggestPicAdapter
import com.gh.gamecenter.suggest.SuggestSelectGameAdapter
import com.halo.assistant.HaloApp
import com.lightgame.utils.Util_System_Keyboard
import com.lightgame.utils.Utils
import io.reactivex.disposables.Disposable
import okhttp3.MediaType
import okhttp3.RequestBody
import java.io.File
import java.util.*
import kotlin.collections.ArrayList
import kotlin.collections.HashMap
import kotlin.collections.component1
import kotlin.collections.component2
import kotlin.collections.set

class GameUploadFragment : ToolbarFragment() {

    private var mAdapter: SuggestPicAdapter? = null
    private var mIconAdapter: SuggestPicAdapter? = null
    private var mSelectGameDialog: Dialog? = null
    private lateinit var mBinding: FragmentGameUploadBinding
    private lateinit var mInstallGameEntity: InstallGameEntity
    private lateinit var mUploadDialog: UploadScheduleDialog
    private lateinit var mViewModel: GameUploadViewModel
    private var mDisposable: Disposable? = null
    private var mUploadFileDisposable: Disposable? = null
    private val mPathMap = LinkedHashMap<String, String>()
    private var mIsOnline: String = ""//是否需要联网
    private var mGameLanguage: String = ""//游戏语言
    private var mGameType: String = ""//游戏类型
    private val mTags = arrayListOf<String>()//游戏标签
    private val mMaxTagSize = 10
    private var mApkUrl: String = ""
    private var mUploadProgressDisposable: Disposable? = null

    override fun getLayoutId(): Int = 0

    override fun getInflatedLayout(): View {
        return FragmentGameUploadBinding.inflate(LayoutInflater.from(requireContext()), null, false).apply {
            mBinding = this
        }.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        setNavigationTitle(getString(R.string.title_game_upload))

        val factory = GameUploadViewModel.Factory(HaloApp.getInstance().application)
        mViewModel = ViewModelProviders.of(this, factory).get(GameUploadViewModel::class.java)
        mViewModel.upLoadSuccess.observe(viewLifecycleOwner, Observer {
            if (it) {
                ToastUtils.showToast("上传成功")
                MtaHelper.onEvent("游戏上传", "游戏上传", "上传成功")
                mUploadDialog.dismiss()
                requireActivity().finish()
            } else {
                mUploadDialog.uploadFail()
            }
        })

        mBinding.gameLabelTv.text = getString(R.string.upload_game_label).fromHtml()
        mBinding.gameIconTitleTv.text = getString(R.string.upload_game_icon).fromHtml()
        mBinding.tvInstallationPackage.text = getString(R.string.upload_game_pkg).fromHtml()
        mBinding.tvGameName.text = getString(R.string.suggestion_game_name).fromHtml()
        mBinding.tvGameIntro.text = getString(R.string.upload_game_intro).fromHtml()
        mBinding.tvScreenshot.text = getString(R.string.upload_game_pic).fromHtml()

        mViewModel.uploadGameTips.observe(viewLifecycleOwner, Observer {
            mBinding.remindTv.visibility = View.VISIBLE
            val remindText = "  $it"
            mBinding.remindTv.text = SpanBuilder(remindText).image(0, 1, R.drawable.ic_game_upload_remind).build()
        })
        mViewModel.getUploadGamesTips()

        mBinding.rvScreenshot.apply {
            layoutManager = object : GridLayoutManager(requireContext(), 5) {
                override fun canScrollVertically(): Boolean {
                    return false
                }
            }
            mAdapter = SuggestPicAdapter(requireContext(), 5, object : OnListClickListener {
                override fun <T : Any?> onListClick(view: View?, position: Int, data: T) {
                    MtaHelper.onEvent("游戏上传", "游戏图片", "添加图片")
                    val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
                    startActivityForResult(intent, MEDIA_STORE_REQUEST)
                }
            }, SuggestPicAdapter.OnItemDeleteListener { MtaHelper.onEvent("游戏上传", "游戏图片", "删除图片") })
            mAdapter?.setPicItem(R.layout.game_upload_pic_item)
            mAdapter?.setSuggestAddPicIcon(R.drawable.icon_pic_add)
            adapter = mAdapter
        }

        mBinding.gameIconRv.apply {
            layoutManager = object : GridLayoutManager(requireContext(), 5) {
                override fun canScrollVertically(): Boolean {
                    return false
                }
            }
            mIconAdapter = SuggestPicAdapter(requireContext(), 1, object : OnListClickListener {
                override fun <T : Any?> onListClick(view: View?, position: Int, data: T) {
                    MtaHelper.onEvent("游戏上传", "游戏图标", "添加图片")
                    val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
                    startActivityForResult(intent, MEDIA_ICON_STORE_REQUEST)
                }
            }, SuggestPicAdapter.OnItemDeleteListener { MtaHelper.onEvent("游戏上传", "游戏图标", "删除图片") })
            mIconAdapter?.setPicItem(R.layout.game_upload_pic_item)
            mIconAdapter?.setSuggestAddPicIcon(R.drawable.icon_pic_add)
            adapter = mIconAdapter
        }

        val privacyContent = SpannableStringBuilder("我已阅读并同意《开发者协议》")
        privacyContent.setSpan(object : ClickableSpan() {

            override fun updateDrawState(ds: TextPaint) {
                super.updateDrawState(ds)
                ds.color = resources.getColor(R.color.theme_font)
                ds.isUnderlineText = false
            }

            override fun onClick(widget: View) {
                startActivity(WebActivity.getUploadPolicyIntent(requireContext()))
            }
        }, 7, privacyContent.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)

        mBinding.tvProtocol.text = privacyContent
        mBinding.tvProtocol.movementMethod = LinkMovementMethod()

        initListener()

        val policyDialogFragment = GameResourcePolicyDialogFragment()
        policyDialogFragment.show(childFragmentManager, "GameResourcePolicyDialogFragment")

        dismissDialogFragment()
    }

    private fun initListener() {

        mBinding.chooseGameLl.setOnClickListener {
            MtaHelper.onEvent("游戏上传", "安装包", "点我选择")
            showSelectDialog()
        }
        mBinding.gameIsNetworkingRg.setOnCheckedChangeListener { _, checkedId ->
            when (checkedId) {
                R.id.gameNetworkingRb -> {
                    mIsOnline = "yes"
                    MtaHelper.onEvent("游戏上传", "是否联网", "需要联网")
                }
                R.id.gameNoNetworkingRb -> {
                    mIsOnline = "no"
                    MtaHelper.onEvent("游戏上传", "是否联网", "无需联网")
                }
            }
        }
        mBinding.gameLanguageRg.setOnCheckedChangeListener { _, checkedId ->
            when (checkedId) {
                R.id.gameLanguageChineseRb -> {
                    mGameLanguage = "中文"
                    MtaHelper.onEvent("游戏上传", "游戏语言", "中文")
                }
                R.id.gameLanguageEnglishRb -> {
                    mGameLanguage = "英文"
                    MtaHelper.onEvent("游戏上传", "游戏语言", "英文")
                }
                R.id.gameLanguageOtherRb -> {
                    mGameLanguage = "其他"
                    MtaHelper.onEvent("游戏上传", "游戏语言", "其他")
                }
            }
        }
        mBinding.gameTypeRg.setOnCheckedChangeListener { _, checkedId ->
            when (checkedId) {
                R.id.gameTypeLocalRb -> {
                    mGameType = "local"
                    MtaHelper.onEvent("游戏上传", "游戏类型", "单机")
                }
                R.id.gameTypeOnlineRb -> {
                    mGameType = "online"
                    MtaHelper.onEvent("游戏上传", "游戏类型", "网游")
                }
                R.id.gameTypeOtherRb -> {
                    mGameType = "other"
                    MtaHelper.onEvent("游戏上传", "游戏类型", "其他")
                }
            }
        }

        mBinding.addGameLabeTv.setOnClickListener {
            MtaHelper.onEvent("游戏上传", "游戏标签", "添加标签")
            if (mTags.size < mMaxTagSize) {
                showAddTagDialog()
            } else {
                ToastUtils.showToast("游戏标签最多添加${mMaxTagSize}个")
            }
        }
        mBinding.suggestPostBtn.setOnClickListener {
            commit()
        }
    }

    private fun commit() {
        MtaHelper.onEvent("游戏上传", "提交", "提交")
        if (TextUtils.isEmpty(mBinding.tvChoose.text.toString())) {
            ToastUtils.showToast("请先选择游戏安装包")
            return
        }
        if (mIconAdapter!!.fileList.size == 0) {
            ToastUtils.showToast("请先选择游戏图标")
            return
        }
        if (TextUtils.isEmpty(mBinding.etGameName.text.toString())) {
            ToastUtils.showToast("请先填写游戏名字")
            return
        }
        if (mTags.isEmpty()) {
            ToastUtils.showToast("请先填写游戏标签")
            return
        }
        if (TextUtils.isEmpty(mBinding.etGameIntro.text.toString())) {
            ToastUtils.showToast("请先填写游戏简介")
            return
        }
        if (mAdapter!!.fileList.size == 0) {
            ToastUtils.showToast("请先选择游戏截图")
            return
        }
        if (!mBinding.tvProtocol.isChecked) {
            ToastUtils.showToast("请先同意开发者协议")
            return
        }
        if (!::mUploadDialog.isInitialized) {
            mUploadDialog = UploadScheduleDialog()
        }
        mUploadDialog.onClickListener = getUploadClickListener()
        mUploadDialog.show(childFragmentManager, "upload")

        uploadApk(mInstallGameEntity.gamePath ?: "")
    }

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

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

    private fun dismissDialogFragment() {
        (childFragmentManager.findFragmentByTag("upload")
                as? UploadScheduleDialog)?.run {
            dismissAllowingStateLoss()
        }
    }

    //获取未上传图片
    private fun getFileList(): List<String> {
        val fileList = arrayListOf<String>()
        fileList.addAll(mIconAdapter!!.fileList)
        fileList.addAll(mAdapter!!.fileList)
        if (mPathMap.isEmpty()) {
            return fileList
        }
        fileList.addAll(mAdapter!!.fileList)
        for ((key, _) in mPathMap) {
            fileList.remove(key)
        }
        return fileList
    }

    //上传图片
    private fun uploadPicture(fileList: List<String>) {
        if (fileList.isEmpty()) return
        mDisposable = UploadImageUtils.uploadImageListOneByOne(
            UploadImageUtils.UploadType.game_upload, fileList, false,
            object : UploadImageUtils.OnUploadImageListCountListener {
                override fun onSuccess(map: Map<String, String>) {
                    mPathMap.putAll(map)
                    // 从90%开始增加
                    val progress =
                        324 + 36 / (mIconAdapter!!.fileList.size + mAdapter!!.fileList.size + 1) * (mPathMap.size + 1)
                    mUploadDialog.updateProgress(progress)
                }

                override fun onFinish() {
                    mDisposable?.dispose()
                    uploadGames()
                }

                override fun onError() {
                    mPathMap.clear()
                    mUploadDialog.uploadFail()
                }
            })
    }

    //上传apk
    private fun uploadApk(apkPath: String) {
        // 假进度，30秒渐增到90%，若30秒内已经上传完APK，则不再渐增，立刻到90%
        mUploadProgressDisposable = countDownTimer(30) { finish, time ->
            if (finish) {
                mUploadDialog.updateProgress(324) //即90%
            } else {
                val progress = 3 * (30 - time.toInt()) * 360 / 100
                mUploadDialog.updateProgress(progress)
            }
        }

        mUploadFileDisposable = OssUploadUtils.uploadFile(
            apkPath,
            OssUploadUtils.UploadType.GAME,
            object : OssUploadUtils.OnUploadFileListener {
                override fun onSuccess(url: String) {
                    mApkUrl = url
                    mUploadProgressDisposable?.dispose()
                    mUploadFileDisposable?.dispose()
                    mUploadDialog.updateProgress(324) // 上传完APK就到90%
                    uploadPicture(getFileList())
                }

                override fun onError(e: Throwable?) {
                    mUploadDialog.uploadFail()
                }
            })
    }

    //上传游戏
    private fun uploadGames() {
        val imageList = ArrayList<String>()
        var index = 0
        var mGameIcon = ""
        for ((_, value) in mPathMap) {
            if (index == 0) {
                mGameIcon = value
            } else {
                imageList.add(value)
            }
            index++
        }
        val requestMap = HashMap<String, Any>()
        requestMap["icon"] = mGameIcon
        requestMap["package_url"] = mApkUrl
        requestMap["tags"] = mTags
        requestMap["package_name"] = mBinding.tvChoose.text.toString()
        requestMap["size"] = mInstallGameEntity.gameSize
        requestMap["version"] = mInstallGameEntity.gameVersion ?: ""
        requestMap["name"] = mBinding.etGameName.text.toString()
        requestMap["des"] = mBinding.etGameIntro.text.toString()
        requestMap["images"] = imageList
        requestMap["video"] = mBinding.gameVideoPathEt.text.toString()
        requestMap["developer_say"] = mBinding.gameDeveloperWordsEt.text.toString()
        if (mIsOnline.isNotEmpty()) {
            requestMap["is_online"] = mIsOnline
        }
        if (mGameLanguage.isNotEmpty()) {
            requestMap["language"] = mGameLanguage
        }
        if (mGameType.isNotEmpty()) {
            requestMap["type"] = mGameType
        }

        val body = RequestBody.create(
            MediaType.parse("application/json"),
            GsonUtils.toJson(requestMap)
        )
        mViewModel.uploadGames(body)
    }


    private fun showSelectDialog() {
        val view = View.inflate(requireContext(), R.layout.dialog_suggest_game, null)
        val recyclerView = view.findViewById<RecyclerView>(R.id.dialog_suggest_game_rv)
        val back = view.findViewById<View>(R.id.dialog_suggest_game_back)
        val pb = view.findViewById<ProgressBar>(R.id.dialog_suggest_game_load)
        val manualBtn = view.findViewById<TextView>(R.id.dialog_suggest_manual)
        val titleTv = view.findViewById<TextView>(R.id.titleTv)
        recyclerView.layoutManager = GridLayoutManager(requireContext(), 4)
        recyclerView.adapter = SuggestSelectGameAdapter(this@GameUploadFragment, pb)
        titleTv.text = "请选择你要上传的游戏"
        manualBtn.text = "从设备上选择"

        mSelectGameDialog = Dialog(requireContext())
        mSelectGameDialog?.apply {
            requestWindowFeature(Window.FEATURE_NO_TITLE)
            setCanceledOnTouchOutside(false)
            setContentView(view)
            show()
        }

        back.setOnClickListener {
            MtaHelper.onEvent("游戏上传", "安装包", "关闭")
            mSelectGameDialog?.cancel()
        }
        manualBtn.setOnClickListener {
            MtaHelper.onEvent("游戏上传", "安装包", "从设备上选择")
            val intent = CleanApkActivity.getIntent(requireContext(), true)
            startActivityForResult(intent, CHOOSE_LOCAL_APK)
        }
    }

    override fun loadDone(obj: Any?) {
        super.loadDone(obj)
        mSelectGameDialog?.cancel()
        if (obj is InstallGameEntity) run {
            mInstallGameEntity = obj
            mBinding.chooseGameLl.background = null
            mBinding.chooseGameLl.setPadding(0, 0, 0, 0)
            mBinding.chooseGameIconIv.visibility = View.GONE
            mBinding.tvChoose.text = mInstallGameEntity.packageName
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (data == null) return
        if (requestCode == MEDIA_STORE_REQUEST || requestCode == MEDIA_ICON_STORE_REQUEST) {
            val selectedImage = data.data ?: return
            val filePathColumn = arrayOf(MediaStore.Images.Media.DATA)

            val cursor = requireContext().contentResolver.query(selectedImage, filePathColumn, null, null, null)
                ?: return
            cursor.moveToFirst()

            try {
                val columnIndex = cursor.getColumnIndex(filePathColumn[0])
                val picturePath = cursor.getString(columnIndex)
                cursor.close()

                Utils.log("picturePath = $picturePath")

                val file = File(picturePath)
                if (file.length() > 5 * 1024 * 1024) {
                    ToastUtils.showToast(getString(R.string.pic_max_hint, 5))
                } else {
                    if (requestCode == MEDIA_STORE_REQUEST) {
                        mAdapter!!.addFileList(picturePath)
                    } else {
                        mIconAdapter!!.addFileList(picturePath)
                    }
                }
            } catch (e: Exception) {
                ToastUtils.showToast(e.message ?: "")
            }
        } else if (requestCode == CHOOSE_LOCAL_APK) {
            val packageName = data.getStringExtra(EntranceConsts.KEY_PACKAGENAME) ?: ""
            val gamePath = data.getStringExtra(EntranceConsts.KEY_PATH) ?: ""
            val version = PackageUtils.getVersionNameByPackageName(packageName)
            val length = File(gamePath).length()
            if (length > 5 * 1024 * 1024 * 1024) {
                ToastUtils.showToast(getString(R.string.apk_max_size_hint, 5))
                return
            }
            mInstallGameEntity = InstallGameEntity().apply {
                this.packageName = packageName
                this.gameSize = length
                this.gamePath = gamePath
                this.gameVersion = version
            }
            loadDone(mInstallGameEntity)
        }
    }

    override fun onBackPressed(): Boolean {
        if (!TextUtils.isEmpty(mBinding.tvChoose.text.toString()) ||
            !TextUtils.isEmpty(mBinding.etGameName.text.toString()) ||
            !TextUtils.isEmpty(mBinding.etGameIntro.text.toString()) ||
            !TextUtils.isEmpty(mBinding.gameDeveloperWordsEt.text.toString()) ||
            !TextUtils.isEmpty(mBinding.gameVideoPathEt.text.toString()) ||
            mIsOnline.isNotEmpty() ||
            mGameLanguage.isNotEmpty() ||
            mGameType.isNotEmpty() ||
            mIconAdapter!!.fileList.size > 0 ||
            mTags.size > 0 ||
            mAdapter!!.fileList.size > 0
        ) {
            DialogHelper.showDialog(
                requireContext(),
                "提示",
                "确定要退出吗？已保存的内容将会消失",
                "不了",
                "确定",
                cancelClickCallback = { activity?.finish() },
                extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true)
            )
            return true
        }
        return super.onBackPressed()
    }

    private fun showAddTagDialog() {
        val dialog = Dialog(requireContext())
        val view = View.inflate(requireContext(), R.layout.dialog_modify_nickname, null)
        val title = view.findViewById<TextView>(R.id.dialog_nickname_title)
        val input = view.findViewById<EditText>(R.id.dialog_nickname_input)
        title.text = "新建标签"
        input.hint = ""
        input.setSelection(input.text.length)
        input.filters = arrayOf(TextHelper.getFilter(6, "标签最多6个字"))
        // 取消按钮
        view.findViewById<TextView>(R.id.dialog_nickname_cancel).setOnClickListener { dialog.dismiss() }
        // 确定按钮
        view.findViewById<TextView>(R.id.dialog_nickname_confirm).setOnClickListener {
            if (!TextUtils.isEmpty(input.text.toString().trim())) {
                addTag(input.text.toString().trim())
                Util_System_Keyboard.hideSoftKeyboard(requireContext(), input)
                dialog.dismiss()
            } else {
                ToastUtils.showToast(getString(R.string.vote_empty_hint))
            }
        }
        dialog.setOnDismissListener {
            Util_System_Keyboard.hideSoftKeyboard(activity)
        }
        dialog.setCancelable(false)
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
        dialog.setContentView(view)
        dialog.show()
        mBaseHandler.postDelayed({ Util_System_Keyboard.showSoftKeyboard(requireContext(), input) }, 300)
    }

    private fun addTag(tag: String) {
        if (!mTags.contains(tag)) {
            val labelView = LayoutInflater.from(requireContext()).inflate(R.layout.item_game_upload_label, null, false)
            val labelTv = labelView.findViewById<TextView>(R.id.labelTv)
            labelTv.text = tag
            labelView.findViewById<View>(R.id.picDelIv).setOnClickListener {
                if (mTags.contains(tag)) {
                    MtaHelper.onEvent("游戏上传", "游戏标签", "删除标签")
                    mBinding.gameLabelFl.removeView(labelView)
                    mTags.remove(tag)
                    mBinding.gameLabelFl.goneIf(mTags.isEmpty())
                    mBinding.addGameLabeTv.goneIf(mTags.size == mMaxTagSize)
                }
            }
            mBinding.gameLabelFl.visibility = View.VISIBLE
            mTags.add(tag)
            mBinding.gameLabelFl.addView(labelView)
            mBinding.addGameLabeTv.goneIf(mTags.size == mMaxTagSize)
        } else {
            ToastUtils.showToast("标签已存在")
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        mDisposable?.dispose()
        mUploadProgressDisposable?.dispose()
        mUploadFileDisposable?.dispose()
    }

    companion object {
        const val MEDIA_STORE_REQUEST = 100
        const val MEDIA_ICON_STORE_REQUEST = 101
        const val MEDIA_APK_STORE_REQUEST = 102
        const val CHOOSE_LOCAL_APK = 103
    }
}