package com.cherry.lib.doc.widget

import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.res.ColorStateList
import android.graphics.Color
import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.RelativeLayout
import android.widget.Toast
import androidx.core.net.toUri
import coil.load
import com.blankj.utilcode.util.UriUtils
import com.cherry.lib.doc.R
import com.cherry.lib.doc.bean.DocEngine
import com.cherry.lib.doc.bean.DocMovingOrientation
import com.cherry.lib.doc.bean.DocSourceType
import com.cherry.lib.doc.bean.FileType
import com.cherry.lib.doc.databinding.DocViewBinding
import com.cherry.lib.doc.interfaces.OnDocPageChangeListener
import com.cherry.lib.doc.office.IOffice
import com.cherry.lib.doc.office.ss.control.SSControl
import com.cherry.lib.doc.util.FileUtils
import com.cherry.lib.doc.util.ViewUtils.hide
import com.cherry.lib.doc.util.ViewUtils.show
import java.io.File

/*
 * -----------------------------------------------------------------
 * Copyright (C) 2018-2028, by Victor, All rights reserved.
 * -----------------------------------------------------------------
 * File: PdfView
 * Author: Victor
 * Date: 2023/10/30 11:30
 * Description: 
 * -----------------------------------------------------------------
 */

class DocView : FrameLayout {

    private val TAG = "DocView"

    var mActivity: Activity? = null
    private var mPoiViewer: PoiViewer? = null
    private var mMovingOrientation = DocMovingOrientation.HORIZONTAL
    private var engine = DocEngine.INTERNAL
    private var showDivider = true
    private var showPageNum = true
    private var divider: Drawable? = null
    var enableLoadingForPages: Boolean = true
    var pbDefaultHeight = 2
    var pbHeight: Int = pbDefaultHeight
    var pbDefaultColor = Color.RED
    var pbColor: Int = pbDefaultColor
    var pageMargin: Rect = Rect(0, 0, 0, 0)
    var mOnDocPageChangeListener: OnDocPageChangeListener? = null
    var sourceFilePath: String? = null
    var mViewPdfInPage: Boolean = true

    var iOffice: IOffice? = null

    constructor(context: Context) : this(context, null)
    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
    constructor(context: Context, attrs: AttributeSet?, defStyle: Int) : super(context, attrs, defStyle) {
        initView(attrs, defStyle)
    }

    private lateinit var binding: DocViewBinding

    fun initView(attrs: AttributeSet?, defStyle: Int) {
        inflate(context, R.layout.doc_view, this)
        binding = DocViewBinding.bind(this)

        val typedArray =
            context.obtainStyledAttributes(attrs, R.styleable.DocView, defStyle, 0)
        val orientation =
            typedArray.getInt(R.styleable.DocView_dv_moving_orientation, DocMovingOrientation.HORIZONTAL.orientation)
        mMovingOrientation = DocMovingOrientation.values().first { it.orientation == orientation }
        val engineValue =
            typedArray.getInt(R.styleable.DocView_dv_engine, DocEngine.INTERNAL.value)
        engine = DocEngine.values().first { it.value == engineValue }
        showDivider = typedArray.getBoolean(R.styleable.DocView_dv_showDivider, true)
        showPageNum = typedArray.getBoolean(R.styleable.DocView_dv_show_page_num, true)
        divider = typedArray.getDrawable(R.styleable.DocView_dv_divider)
        enableLoadingForPages = typedArray.getBoolean(R.styleable.DocView_dv_enableLoadingForPages, enableLoadingForPages)
        pbHeight = typedArray.getDimensionPixelSize(R.styleable.DocView_dv_page_pb_height, pbDefaultHeight)
        pbColor = typedArray.getColor(R.styleable.DocView_dv_page_pb_color, pbDefaultColor)

        val marginDim = typedArray.getDimensionPixelSize(R.styleable.DocView_dv_page_margin, 0)
        pageMargin = Rect(marginDim, marginDim, marginDim, marginDim).apply {
            top = typedArray.getDimensionPixelSize(R.styleable.DocView_dv_page_marginTop, top)
            left = typedArray.getDimensionPixelSize(R.styleable.DocView_dv_page_marginLeft, left)
            right = typedArray.getDimensionPixelSize(R.styleable.DocView_dv_page_marginRight, right)
            bottom = typedArray.getDimensionPixelSize(R.styleable.DocView_dv_page_marginBottom, bottom)
        }


        val layoutParams = binding.mPlLoadProgress.layoutParams
        layoutParams.height = pbHeight
        binding.mPlLoadProgress.layoutParams = layoutParams

        binding.mPlLoadProgress.progressTintList = ColorStateList.valueOf(pbColor)

        typedArray.recycle()
    }

    fun openDoc(
        activity: Activity, docUrl: String?, docSourceType: Int,
    ) {
        mActivity = activity
        openDoc(activity, docUrl, docSourceType, -1, false)
    }

    @SuppressLint("ObsoleteSdkInt")
    fun openDoc(
        activity: Activity?,
        docUrl: String?,
        docSourceType: Int,
        fileType: Int,
        viewPdfInPage: Boolean = false,
    ) {
        var fileType = fileType
        var docUrl = docUrl
        var docSourceType = docSourceType
        if (docUrl != null && docSourceType == DocSourceType.URI && fileType == -1) {
            // 如果是URI类型，且文件类型为-1，则获取一下文件类型，保证正确读取
            val uri = docUrl.toUri()
            Log.d(TAG, "openDoc reset uri = $uri")
            val file = UriUtils.uri2File(uri)
            if (file != null) {
                var mimeType = ""
                fileType = FileUtils.getFileTypeForUrl(file.absolutePath)
                if (fileType == FileType.NOT_SUPPORT) {
                    mimeType = FileUtils.getFileMimeType(context, uri) ?: "*/*"
                    fileType = FileUtils.getFileTypeForUrl(FileUtils.mimeExtMap[mimeType] ?: "")
                }
                docUrl = file.absolutePath
                docSourceType = DocSourceType.PATH
                Log.d(TAG, "openDoc reset url = $docUrl")
                Log.d(TAG, "openDoc reset docSourceType = $docSourceType")
                Log.d(TAG, "openDoc reset fileType = $fileType, mimeType = $mimeType")
            } else {
                Log.d(TAG, "file = null")
            }
        }
        Log.e(TAG, "openDoc()......fileType = $fileType")
        mActivity = activity
        mViewPdfInPage = viewPdfInPage
        if (docSourceType == DocSourceType.PATH) {
            sourceFilePath = docUrl
        } else {
            sourceFilePath = null
        }
        var type = FileUtils.getFileTypeForUrl(docUrl)
        if (fileType > 0) {
            type = fileType
        }
        when (type) {
            FileType.PDF -> {
                Log.e(TAG, "openDoc()......PDF")
                binding.mFlDocContainer.hide()
                binding.mIvImage.hide()

            }

            FileType.IMAGE -> {
                if (showPageNum) {
                    showPageNum = false
                }
                Log.e(TAG, "openDoc()......")
                binding.mFlDocContainer.hide()
                binding.mIvImage.show()
                if (docSourceType == DocSourceType.PATH) {
                    Log.e(TAG, "openDoc()......PATH")
                    binding.mIvImage.load(File(docUrl))
                } else {
                    Log.e(TAG, "openDoc()......URL")
                    binding.mIvImage.load(docUrl)
                }
            }

            FileType.NOT_SUPPORT -> {
            }

            else -> {
                Log.e(TAG, "openDoc()......ELSE")
                if (showPageNum) {
                    showPageNum = false
                }
                binding.mFlDocContainer.show()
                binding.mIvImage.hide()
                activity?.let { showDoc(it, binding.mFlDocContainer, docUrl, docSourceType, fileType) }
            }
        }
    }

    var singleTapAction: (() -> Unit)? = null
    var getPageNumberAction: ((current: Int, total: Int) -> Unit)? = null

    fun showDoc(activity: Activity, mDocContainer: ViewGroup?, url: String?, docSourceType: Int, fileType: Int) {
        Log.e(TAG, "showDoc()......")
        iOffice = object : IOffice() {
            override fun onEventMethod(
                v: View?,
                e1: MotionEvent?,
                e2: MotionEvent?,
                xValue: Float,
                yValue: Float,
                eventMethodType: Byte
            ): Boolean {
                Log.e(TAG, "onEventMethod ${e1?.action} ${MotionEvent.ACTION_DOWN}")
                return super.onEventMethod(v, e1, e2, xValue, yValue, eventMethodType)
            }

            override fun singleTap() {
                Log.e(TAG, "singleTap")
                singleTapAction?.invoke()
            }

            override fun getPageNumber(current: Int, total: Int) {
                getPageNumberAction?.invoke(current, total)
            }

            override fun getActivity(): Activity {
                return activity
            }

            override fun openFileFinish() {
                mDocContainer?.postDelayed({
                    mDocContainer.removeAllViews()
                    mDocContainer.addView(
                        view,
                        RelativeLayout.LayoutParams(
                            RelativeLayout.LayoutParams.MATCH_PARENT,
                            RelativeLayout.LayoutParams.MATCH_PARENT
                        )
                    )
                }, 200)
            }

            override fun openFileFailed() {
                try {
                    if (mPoiViewer == null) {
                        mPoiViewer = PoiViewer(context)
                    }
                    mPoiViewer?.loadFile(
                        binding.mFlDocContainer, sourceFilePath ?: ""
                    )
                } catch (e: Exception) {
                    e.printStackTrace()
                    Toast.makeText(context, R.string.open_failed, Toast.LENGTH_SHORT).show()
                }
            }

            override fun getAppName(): String {
                return context.resources.getString(R.string.loading)
            }

            override fun getTemporaryDirectory(): File {
                val file = activity.getExternalFilesDir(null)
                return file ?: activity.filesDir
            }

            override fun fullScreen(fullscreen: Boolean) {
            }

            override fun getMovingOrientation(): Int {
                return mMovingOrientation.orientation
            }

        }
        iOffice?.openFile(url, docSourceType, fileType.toString())
    }


    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        onDestroy()
    }


    fun onDestroy() {
        mPoiViewer?.recycle()
        mOnDocPageChangeListener = null
    }
}