package com.base.pdfviewerscannerwhite.ui.document.pdf

import android.animation.Animator
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.annotation.SuppressLint
import android.content.Intent
import android.content.pm.ActivityInfo
import android.graphics.Color
import android.util.DisplayMetrics
import android.view.View
import android.view.animation.Animation
import android.view.animation.TranslateAnimation
import android.view.inputmethod.EditorInfo
import androidx.activity.addCallback
import androidx.core.content.ContextCompat
import androidx.core.widget.addTextChangedListener
import androidx.lifecycle.lifecycleScope
import com.artifex.mupdfdemo.Annotation
import com.artifex.mupdfdemo.Hit
import com.artifex.mupdfdemo.MuPDFCore
import com.artifex.mupdfdemo.MuPDFPageAdapter
import com.artifex.mupdfdemo.MuPDFReaderView
import com.artifex.mupdfdemo.MuPDFReaderViewListener
import com.artifex.mupdfdemo.MuPDFView
import com.artifex.mupdfdemo.SearchTask
import com.artifex.mupdfdemo.SearchTaskResult
import com.base.pdfviewerscannerwhite.R
import com.base.pdfviewerscannerwhite.ads.AdmobHelper
import com.base.pdfviewerscannerwhite.ads.AdmobHelper.isShowCloseDocument
import com.base.pdfviewerscannerwhite.ads.admob.AdmobInterstitialUtils
import com.base.pdfviewerscannerwhite.ads.admob.AdmobNativeUtils
import com.base.pdfviewerscannerwhite.bean.ConstObject.DO_SAVE_PDF
import com.base.pdfviewerscannerwhite.bean.ConstObject.haveGuideGesture
import com.base.pdfviewerscannerwhite.bean.PdfPageBean
import com.base.pdfviewerscannerwhite.databinding.ActivityPdfBinding
import com.base.pdfviewerscannerwhite.helper.BaseActivity
import com.base.pdfviewerscannerwhite.helper.MyApplication
import com.base.pdfviewerscannerwhite.ui.view.PdfDialog.showPdfMoreDialog
import com.base.pdfviewerscannerwhite.utils.KeyBoardUtils.hideKeyboard
import com.base.pdfviewerscannerwhite.utils.KeyBoardUtils.showKeyBoard
import com.base.pdfviewerscannerwhite.utils.LogEx
import com.base.pdfviewerscannerwhite.utils.SpStringUtils
import com.base.pdfviewerscannerwhite.utils.SpStringUtils.LAST_VIEW_KEY
import com.base.pdfviewerscannerwhite.utils.ToastUtils.toast
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.io.File


class PdfActivity : BaseActivity<ActivityPdfBinding>(), PdfView {

    private val TAG = "PdfActivity"
    private lateinit var pdfPresenter: PdfPresenter
    private lateinit var pdfPageAdapter: PdfPagerAdapter

    private var muPDFCore: MuPDFCore? = null // 加载mupdf.so文件
    private var searchTask: SearchTask? = null

    private var uiMode = UI_MODE_NORMAL
    private var saveMode = ""
    private var path: String = ""
    private var uri: String? = null
    private var assets: String? = null
    private var density = 0f

    override val binding: ActivityPdfBinding by lazy {
        ActivityPdfBinding.inflate(layoutInflater)
    }

    override fun onResume() {
        super.onResume()
        updateAppLanguage(MyApplication.pdfLanguage, TAG) {
            MyApplication.pdfLanguage = it
        }
    }

    override fun onPause() {
        super.onPause()
        searchTask?.stop()
    }

    override fun onDestroy() {
        super.onDestroy()
        muPDFCore?.onDestroy()
        AdmobNativeUtils.onDestroy()
    }


    override fun initView() {
        val needRecreate = checkNeedRecreate(MyApplication.pdfLanguage)
        if (needRecreate) return

        val metrics = DisplayMetrics()
        windowManager.defaultDisplay.getMetrics(metrics)
        density = metrics.density

        path = intent.extras?.getString("path") ?: ""
        uri = intent.extras?.getString("uri")
        assets = intent.extras?.getString("assets") ?: ""
        LogEx.logDebug(TAG, "path=$path")
        LogEx.logDebug(TAG, "uri=$uri")

        val file = File(path)
        binding.tvPdfName.text = file.name

        pdfPresenter = PdfPresenter(this, this)

        initAdapter()
        changeNormalUI()

        runCatching {
            muPDFCore = pdfPresenter.openFile(path, uri)
        }

        // 搜索设为空
        SearchTaskResult.set(null)

        if (muPDFCore?.needsPassword() == true) {
            val pwd = intent.extras?.getString("pwd") ?: ""
            val flag = muPDFCore?.authenticatePassword(pwd) ?: false
            if (flag) {
                pdfPresenter.password = pwd
                pdfPageAdapter.setPassword(pwd)
                createPdfUI()
                muPDFCore?.countPages()?.let { pdfPresenter.iniPdfPage(it) }
                SpStringUtils.addSpString(LAST_VIEW_KEY, "${path}_/_${System.currentTimeMillis()}")
            } else {
                toast("unknown error")
                finish()
            }
        } else {
            createPdfUI()
            muPDFCore?.countPages()?.let { pdfPresenter.iniPdfPage(it) }
            SpStringUtils.addSpString(LAST_VIEW_KEY, "${path}_/_${System.currentTimeMillis()}")
        }

        if (!haveGuideGesture) {
            binding.flGuideGesture.visibility = View.VISIBLE
            lifecycleScope.launch(Dispatchers.Main) {
                delay(2000)
                binding.flGuideGesture.visibility = View.GONE
            }
        }

        AdmobNativeUtils.showNativeAd(this, binding.flAd, R.layout.layout_admob_document_in)
    }

    override fun jumpPage(pageIndex: Int) {
        super.jumpPage(pageIndex)
        binding.mupdfReaderView.displayedViewIndex = pageIndex
    }

    private fun iniSetVerticalSeekbar(max: Int) {
        binding.verticalSeekbar.visibility = View.VISIBLE
        binding.verticalSeekbar.showThumb = true
        binding.verticalSeekbar.barBackgroundStartColor = Color.TRANSPARENT
        binding.verticalSeekbar.thumbContainerColor = Color.TRANSPARENT
        binding.verticalSeekbar.thumbPlaceholderDrawable =
            ContextCompat.getDrawable(this, R.mipmap.fanye)
        if (binding.verticalSeekbar.maxValue != max - 1) {
            binding.verticalSeekbar.maxValue = max - 1
        }
    }

    private fun setVerticalSeekbar(current: Int, max: Int) {

        val process = max - current
        LogEx.logDebug(TAG, "process=$process $current $max")
        binding.verticalSeekbar.progress = process
    }

    override fun initListener() {
        val needRecreate = checkNeedRecreate(MyApplication.pdfLanguage)
        if (needRecreate) return

        onBackPressedDispatcher.addCallback {
            hideKeyboard(binding.editSearch)

            if (uiMode == UI_MODE_SEARCH) {
                changeNormalUI()
                cancelSearch()
                return@addCallback
            }
            if (uiMode == UI_MODE_EDITE_SELECT) {
                changeNormalUI()
                cancelOperation()
                return@addCallback
            }
            if (uiMode == UI_MODE_EDITE_SAVE) {
                changeNormalUI()
                cancelOperation()
                return@addCallback
            }

            if (AdmobHelper.isShowCloseDocumentInter() && isShowCloseDocument()) {
                AdmobInterstitialUtils.showInterstitialAd(this@PdfActivity) {
                    if (it) {
                        AdmobHelper.lastCloseDocumentShowAd = System.currentTimeMillis()
                    }
                    binding.root.postDelayed({ finishToMain() }, 500)
                }
            } else {
                binding.root.postDelayed({ finishToMain() }, 500)
            }
        }
        binding.flFanhui.setOnClickListener {
            onBackPressedDispatcher.onBackPressed()
        }

        binding.llHighlight.setOnClickListener {
            saveMode = SAVE_MODE_HIGHLIGHT
            changeEditSelectUI(it)
            binding.mupdfReaderView.setMode(MuPDFReaderView.Mode.Selecting)
        }
        binding.llGlideLine.setOnClickListener {
            saveMode = SAVE_MODE_GLIDE_LINE
            changeEditSelectUI(it)
            binding.mupdfReaderView.setMode(MuPDFReaderView.Mode.Selecting)
        }
        binding.llStrikethrough.setOnClickListener {
            saveMode = SAVE_MODE_STRIKETHROUGH
            changeEditSelectUI(it)
            binding.mupdfReaderView.setMode(MuPDFReaderView.Mode.Selecting)
        }
        binding.llPaintingBrush.setOnClickListener {
            saveMode = SAVE_MODE_PAINTING_BRUSH
            changeEditSelectUI(it)
            binding.mupdfReaderView.setMode(MuPDFReaderView.Mode.Drawing)
        }
        binding.ivWancheng.setOnClickListener {
            changeEditSaveUI()
            binding.mupdfReaderView.setMode(MuPDFReaderView.Mode.Viewing)
        }
        binding.ivBianji.setOnClickListener {
            bianJiScaleXiao {
                changeEditSaveUI()
            }
        }
        binding.ivSearch.setOnClickListener {
            bianJiScaleXiao {
                changeSearchUI()
                showKeyBoard(binding.editSearch)
            }
        }
        binding.editSearch.addTextChangedListener {
            if (SearchTaskResult.get() != null && it.toString() != SearchTaskResult.get().txt) {
                SearchTaskResult.set(null as SearchTaskResult?)
                binding.mupdfReaderView.resetupChildren()
            }
        }
        binding.editSearch.setOnEditorActionListener { v, actionId, event ->
            if (actionId == EditorInfo.IME_ACTION_DONE) {
                search(1)
            }
            false
        }

        binding.tvBtnSave.setOnClickListener {
            PdfLoadingActivity.muPDFCore = muPDFCore
            reallySave()
            startActivity(Intent(this, PdfLoadingActivity::class.java).apply {
                putExtra("doWhat", DO_SAVE_PDF)
                putExtra("srcPath", path)
            })
            finish()
        }
        binding.ivXuanzhuan.setOnClickListener {
            switchOrientation()
        }
        binding.verticalSeekbar.setOnReleaseListener { progress ->
            LogEx.logDebug(TAG, "progress=$progress")
            val total = muPDFCore?.countPages() ?: 0
            val pageIndex = total - 1 - progress

            binding.mupdfReaderView.displayedViewIndex = pageIndex
        }
        binding.flGuideGesture.setOnClickListener {
            haveGuideGesture = true
            binding.flGuideGesture.visibility = View.GONE
        }
        binding.ivMore.setOnClickListener {
            val count = muPDFCore?.countPages() ?: 0
            showPdfMoreDialog(this, count - 1, path)
        }
    }

    /**
     *
     */
    private fun reallySave() {
        var success: Boolean = false
        val pageView = binding.mupdfReaderView.displayedView as MuPDFView
        when (saveMode) {
            SAVE_MODE_HIGHLIGHT -> {
                success = pageView.markupSelection(Annotation.Type.HIGHLIGHT)
            }

            SAVE_MODE_GLIDE_LINE -> {
                success = pageView.markupSelection(Annotation.Type.UNDERLINE)
            }

            SAVE_MODE_STRIKETHROUGH -> {
                success = pageView.markupSelection(Annotation.Type.STRIKEOUT)
            }

            SAVE_MODE_PAINTING_BRUSH -> {
                success = pageView.saveDraw()
            }
        }
        if (!success) {
            toast("nothing to save")
            return
        }
    }


    private fun cancelOperation() {
        val pageView = binding.mupdfReaderView.displayedView as MuPDFView?
        if (pageView != null) {
            pageView.deselectAnnotation()
            pageView.deleteSelectedAnnotation()
            pageView.deselectText()
            pageView.cancelDraw()
        }
        binding.mupdfReaderView.setMode(MuPDFReaderView.Mode.Viewing)
    }

    private fun cancelSearch() {
        SearchTaskResult.set(null)
        binding.mupdfReaderView.resetupChildren()
    }

    /**
     * 有个问题，一旦pdf某页编辑后加个蒙层，搜索功能就是失效了
     */
    private fun search(direction: Int) {
        this.hideKeyboard(binding.editSearch)
        val displayPage: Int = binding.mupdfReaderView.displayedViewIndex
        val r = SearchTaskResult.get()
        val searchPage = r?.pageNumber ?: -1
        searchTask?.go(binding.editSearch.text.toString(), direction, displayPage, searchPage)
    }

    private fun initAdapter() {
        pdfPageAdapter = PdfPagerAdapter(path, uri)
        pdfPageAdapter.clickAction = { pageIndex ->
            binding.mupdfReaderView.displayedViewIndex = pageIndex
        }
        binding.rvPager.adapter = pdfPageAdapter
    }


    private var isShowTopBottomLayout = true
    private fun hideTopBottomLayout() {
        if (isShowTopBottomLayout) {
            isShowTopBottomLayout = false

            hideKeyboard(binding.editSearch)
            val topAnim: Animation = TranslateAnimation(0f, 0f, 0f, -binding.vAnimatorTop.height.toFloat())
            topAnim.setDuration(200)
            topAnim.setAnimationListener(object : Animation.AnimationListener {
                override fun onAnimationStart(animation: Animation) {}
                override fun onAnimationRepeat(animation: Animation) {}
                override fun onAnimationEnd(animation: Animation) {
                    binding.vAnimatorTop.visibility = View.GONE
                }
            })
            binding.vAnimatorTop.startAnimation(topAnim)

            val bottomAnim: Animation = TranslateAnimation(0f, 0f, 0f, binding.vAnimatorBottom.height.toFloat())
            bottomAnim.duration = 200
            bottomAnim.setAnimationListener(object : Animation.AnimationListener {
                override fun onAnimationStart(animation: Animation) {}
                override fun onAnimationRepeat(animation: Animation) {}
                override fun onAnimationEnd(animation: Animation) {
                    binding.vAnimatorBottom.visibility = View.GONE
                }
            })
            binding.vAnimatorBottom.startAnimation(bottomAnim)

            bianJiScaleXiao()
        }

    }

    private fun showTopBottomLayout() {
        if (!isShowTopBottomLayout) {
            isShowTopBottomLayout = true

            val topAnim: Animation = TranslateAnimation(0f, 0f, -binding.vAnimatorTop.height.toFloat(), 0f)
            topAnim.setDuration(200)
            topAnim.setAnimationListener(object : Animation.AnimationListener {
                override fun onAnimationStart(animation: Animation) {
                    binding.vAnimatorTop.visibility = View.VISIBLE
                }

                override fun onAnimationRepeat(animation: Animation) {}
                override fun onAnimationEnd(animation: Animation) {
                }
            })
            binding.vAnimatorTop.startAnimation(topAnim)

            val bottomAnim: Animation = TranslateAnimation(0f, 0f, binding.vAnimatorBottom.height.toFloat(), 0f)
            bottomAnim.duration = 200
            bottomAnim.setAnimationListener(object : Animation.AnimationListener {
                override fun onAnimationStart(animation: Animation) {
                    binding.vAnimatorBottom.visibility = View.VISIBLE
                }

                override fun onAnimationRepeat(animation: Animation) {}
                override fun onAnimationEnd(animation: Animation) {

                }
            })
            binding.vAnimatorBottom.startAnimation(bottomAnim)

            bianJiScaleDa()
        }
    }

    private fun bianJiScaleDa() {
        if (binding.ivBianji.scaleX == 0f) {
            val scaleXAnimator = ObjectAnimator.ofFloat(binding.ivBianji, "scaleX", 0f, 1.0f)
            scaleXAnimator.duration = 200
            val scaleYAnimator = ObjectAnimator.ofFloat(binding.ivBianji, "scaleY", 0f, 1.0f)
            scaleYAnimator.duration = 200

            val animatorSet = AnimatorSet()
            animatorSet.playTogether(scaleXAnimator, scaleYAnimator)
            animatorSet.start()
        }

    }

    private fun bianJiScaleXiao(endAction: (() -> Unit)? = null) {
        if (binding.ivBianji.scaleX == 1f) {
            val scaleXAnimator = ObjectAnimator.ofFloat(binding.ivBianji, "scaleX", 1.0f, 0f)
            scaleXAnimator.duration = 200
            val scaleYAnimator = ObjectAnimator.ofFloat(binding.ivBianji, "scaleY", 1.0f, 0f)
            scaleYAnimator.duration = 200

            val animatorSet = AnimatorSet()
            animatorSet.addListener(object : Animator.AnimatorListener {
                override fun onAnimationStart(animation: Animator) = Unit
                override fun onAnimationEnd(animation: Animator) {
                    endAction?.invoke()
                }

                override fun onAnimationCancel(animation: Animator) = Unit
                override fun onAnimationRepeat(animation: Animator) = Unit
            })
            animatorSet.playTogether(scaleXAnimator, scaleYAnimator)
            animatorSet.start()
        }
    }

    /**
     * 构建pdf的ui
     */
    @SuppressLint("SetTextI18n")
    private fun createPdfUI() {
        if (muPDFCore == null) return

        binding.tvPageCount.text = "1/${muPDFCore?.countPages()}"

        binding.mupdfReaderView.setListener(object : MuPDFReaderViewListener {
            @SuppressLint("SetTextI18n")
            override fun onMoveToChild(i: Int) {
                binding.tvPageCount.text = "${i + 1}/${muPDFCore?.countPages()}"
                pdfPageAdapter.changeSelectPager(i)
                binding.rvPager.scrollToPosition(i)
                setVerticalSeekbar(i + 1, muPDFCore?.countPages() ?: 0)
            }

            override fun onTapMainDocArea() {
                if (isShowTopBottomLayout) {
                    hideTopBottomLayout()
                } else {
                    showTopBottomLayout()
                }
            }

            override fun onDocMotion() {
            }

            override fun onHit(item: Hit?) {
            }
        })

        binding.mupdfReaderView.adapter = MuPDFPageAdapter(this, {}, muPDFCore)

        binding.mupdfReaderView.setBackgroundColor(Color.parseColor("#E0D5FA"))
        binding.mupdfReaderView.setHorizontalScrolling(false)
        searchTask = object : SearchTask(this, muPDFCore) {
            override fun onTextFound(result: SearchTaskResult?) {
                SearchTaskResult.set(result)
                binding.mupdfReaderView.displayedViewIndex = result?.pageNumber ?: 0
                binding.mupdfReaderView.resetupChildren()
            }
        }
    }


    /**
     * 普通模式
     */
    private fun changeNormalUI() {
        uiMode = UI_MODE_NORMAL
        binding.ivWancheng.visibility = View.GONE
        binding.clOperation.visibility = View.GONE
        binding.tvBtnSave.visibility = View.GONE
        binding.editSearch.visibility = View.INVISIBLE

        binding.ivXuanzhuan.visibility = View.VISIBLE
        binding.ivSearch.visibility = View.VISIBLE
        binding.ivMore.visibility = View.VISIBLE
        binding.rvPager.visibility = View.VISIBLE
        binding.tvPdfName.visibility = View.VISIBLE

        bianJiScaleDa()
    }

    /**
     * 搜索模式UI
     */
    private fun changeSearchUI() {
        uiMode = UI_MODE_SEARCH
        binding.ivXuanzhuan.visibility = View.INVISIBLE
        binding.ivMore.visibility = View.GONE
        binding.tvPdfName.visibility = View.INVISIBLE
        binding.rvPager.visibility = View.GONE
        binding.clOperation.visibility = View.GONE

        binding.editSearch.visibility = View.VISIBLE

    }


    /**
     * 编辑选择UI模式
     */
    private fun changeEditSelectUI(view: View) {
        uiMode = UI_MODE_EDITE_SELECT

        binding.tvBtnSave.visibility = View.GONE
        binding.rvPager.visibility = View.GONE
        binding.ivXuanzhuan.visibility = View.INVISIBLE
        binding.ivSearch.visibility = View.INVISIBLE
        binding.ivMore.visibility = View.INVISIBLE

        binding.ivWancheng.visibility = View.VISIBLE


        if (binding.llHighlight == view) {
            binding.llHighlight.setBackgroundColor(Color.parseColor("#F5F5F5"))
        } else {
            binding.llHighlight.setBackgroundColor(Color.TRANSPARENT)
        }
        if (binding.llGlideLine == view) {
            binding.llGlideLine.setBackgroundColor(Color.parseColor("#F5F5F5"))
        } else {
            binding.llGlideLine.setBackgroundColor(Color.TRANSPARENT)
        }
        if (binding.llStrikethrough == view) {
            binding.llStrikethrough.setBackgroundColor(Color.parseColor("#F5F5F5"))
        } else {
            binding.llStrikethrough.setBackgroundColor(Color.TRANSPARENT)
        }
        if (binding.llPaintingBrush == view) {
            binding.llPaintingBrush.setBackgroundColor(Color.parseColor("#F5F5F5"))
        } else {
            binding.llPaintingBrush.setBackgroundColor(Color.TRANSPARENT)
        }
    }


    /**
     * 编辑保持UI模式
     */
    private fun changeEditSaveUI() {
        uiMode = UI_MODE_EDITE_SAVE
        binding.ivWancheng.visibility = View.INVISIBLE
        binding.ivMore.visibility = View.INVISIBLE
        binding.ivXuanzhuan.visibility = View.INVISIBLE
        binding.ivSearch.visibility = View.INVISIBLE

        binding.clOperation.visibility = View.VISIBLE
        binding.tvBtnSave.visibility = View.VISIBLE
        binding.rvPager.visibility = View.VISIBLE

        binding.llHighlight.setBackgroundColor(Color.TRANSPARENT)
        binding.llGlideLine.setBackgroundColor(Color.TRANSPARENT)
        binding.llStrikethrough.setBackgroundColor(Color.TRANSPARENT)
        binding.llPaintingBrush.setBackgroundColor(Color.TRANSPARENT)

    }


    fun switchOrientation() {
        requestedOrientation = if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
            ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
        } else {
            ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
        }
    }

    companion object {

        const val UI_MODE_NORMAL = 0
        const val UI_MODE_SEARCH = 1
        const val UI_MODE_EDITE_SELECT = 2
        const val UI_MODE_EDITE_SAVE = 3

        const val SAVE_MODE_HIGHLIGHT = "Highlight"
        const val SAVE_MODE_GLIDE_LINE = "Glide Line"
        const val SAVE_MODE_STRIKETHROUGH = "Strikethrough"
        const val SAVE_MODE_PAINTING_BRUSH = "Painting Brush"
    }

    override fun initPdfPageRv(items: List<PdfPageBean>) {
        pdfPageAdapter.submitList(items)
        pdfPageAdapter.changeSelectPager(0)
        iniSetVerticalSeekbar(items.size)
    }

}