package com.kdanmobile.reader

import android.arch.lifecycle.LiveData
import android.arch.lifecycle.MutableLiveData
import android.arch.lifecycle.ViewModel
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Color
import android.graphics.RectF
import android.net.Uri
import android.support.v4.content.ContextCompat
import com.kdanmobile.kmpdfkit.annotation.Annotation
import com.kdanmobile.kmpdfkit.annotation.bean.*
import com.kdanmobile.kmpdfkit.contextmenu.KMPDFMenuItem
import com.kdanmobile.kmpdfkit.contextmenu.MenuItemCallback
import com.kdanmobile.kmpdfkit.globaldata.AnnotConfig
import com.kdanmobile.kmpdfkit.globaldata.Config
import com.kdanmobile.kmpdfkit.globaldata.KMPDFAnnotEditMode
import com.kdanmobile.kmpdfkit.manager.KMPDFFactory
import com.kdanmobile.kmpdfkit.manager.controller.*
import com.kdanmobile.kmpdfkit.manager.listener.KMPDFAddAnnotCallback
import com.kdanmobile.kmpdfkit.manager.listener.KMPDFAnnotEditModeChangeListener
import com.kdanmobile.kmpdfkit.pdfcommon.*
import com.kdanmobile.reader.annotationattribute.AnnotationAttribute
import com.kdanmobile.reader.annotationattribute.Brush
import com.kdanmobile.reader.annotationattribute.InkAttribute
import com.kdanmobile.reader.screen.contextmenu.TextBoxContextMenuActionListener
import com.kdanmobile.reader.screen.data.ShapeAttribute
import com.kdanmobile.reader.screen.data.SignatureAttribute
import com.kdanmobile.reader.screen.data.StampAttribute
import com.kdanmobile.reader.screen.data.TextBoxAttribute
import com.kdanmobile.reader.screen.handler.*
import com.kdanmobile.reader.thumb.PdfThumbViewModel
import java.io.File
import java.util.*
import kotlin.collections.ArrayList

class ReaderViewModel(private val pdfSdkLicense: String, private val pdfSdkRsaMsg: String) : ViewModel() {

    enum class ViewDirection(val mode: Config.PDFViewMode) {
        VerticalSinglePageContinues(Config.PDFViewMode.VERTICAL_SINGLE_PAGE_CONTINUES),
        VerticalSinglePage(Config.PDFViewMode.VERTICAL_SINGLE_PAGE),
        HorizontalSinglePage(Config.PDFViewMode.HORIZONTAL_SINGLE_PAGE)
    }

    enum class ReadMode(val mode: Config.ReadMode) {
        READ_MODE_DAY(Config.ReadMode.READ_MODE_DAY),
        READ_MODE_NIGHT(Config.ReadMode.READ_MODE_NIGHT),
        READ_MODE_SOFT(Config.ReadMode.READ_MODE_SOFT),
        MODE_CHROME_WHITE(Config.ReadMode.USER_DEFINED),
        MODE_ETON_BLUE(Config.ReadMode.USER_DEFINED),
        MODE_WHITE_LILAC(Config.ReadMode.USER_DEFINED)
    }

    enum class AnnotationMode {
        None,
        Highlight,
        Strike,
        Underline,
        Ink,
    }

    companion object {
        val DEFAULT_HIGHLIGHT_ATTR = AnnotationAttribute(Color.parseColor("#ffdc1b"), 127)
        val DEFAULT_STRIKE_ATTR = AnnotationAttribute(Color.parseColor("#57d214"), 255)
        val DEFAULT_UNDERLINE_ATTR = AnnotationAttribute(Color.parseColor("#296dd2"), 255)
        val DEFAULT_INK_ATTR = InkAttribute(Color.parseColor("#dd0202"), 255, 1f, Brush.Fountain)
    }

    var file: File? = null
        private set
    val pdfInfo: PDFInfo?
        get() {
            return kmpdfDocumentController?.pdfInfo
        }
    val isPasswordProtected: Boolean
        get() {
            return kmpdfFactory?.needPassWord() ?: false
        }
    var viewDirection = ViewDirection.VerticalSinglePageContinues
        set(value) {
            field = value
            updateViewDirection()
        }
    var readMode = ReadMode.READ_MODE_DAY
        set(value) {
            field = value
            updateReadMode()
        }
    var isCrop = false
        set(value) {
            field = value
            updateCrop()
        }
    val highLightAttributeLiveData = MutableLiveData<AnnotationAttribute>().apply { value = DEFAULT_HIGHLIGHT_ATTR }
    val strikeAttributeLiveData = MutableLiveData<AnnotationAttribute>().apply { value = DEFAULT_STRIKE_ATTR }
    var underLineAttributeLiveData = MutableLiveData<AnnotationAttribute>().apply { value = DEFAULT_UNDERLINE_ATTR }
    var inkAttributeLiveData = MutableLiveData<InkAttribute>().apply { value = DEFAULT_INK_ATTR }

    private var isVerified = false

    val readerModel = ReaderModel()
    private val kmpdfFactory: KMPDFFactory?
        get() = readerModel.kmpdfFactory
    private val kmpdfDocumentController: KMPDFDocumentController?
        get() = readerModel.kmpdfDocumentController
    val isOpenedFileLiveData = MutableLiveData<Boolean>().apply { value = false }
    val fileNameLiveData = MutableLiveData<String>()
    val annotationModeLiveData = MutableLiveData<AnnotationMode>().apply { value = AnnotationMode.None }
    val annotationEitModeLiveData = MutableLiveData<KMPDFAnnotEditMode.Mode>().apply { value = KMPDFAnnotEditMode.Mode.NULL }
    var isCopyModeLiveData = MutableLiveData<Boolean>().apply { value = false }

    val pageIndexLiveData: LiveData<Int>
        get() = mPageIndexLiveData
    val isPageInBookmarksLiveData: LiveData<Boolean>
        get() = mIsPageInBookmarksLiveData

    private val mPageIndexLiveData = MutableLiveData<Int>().apply { value = 0 }
    private val mIsPageInBookmarksLiveData = MutableLiveData<Boolean>().apply { value = false }

    enum class LeftToolbarType {
        NONE, THUMBNAIL, BOOKMARK, OUTLINE, SEARCH
    }

    val leftToolbarTypeLiveData: LiveData<LeftToolbarType>
        get() = mLeftToolbarTypeLiveData
    private val mLeftToolbarTypeLiveData = MutableLiveData<LeftToolbarType>().apply { value = LeftToolbarType.NONE }

    val isLeftToolbarOpenLiveData: LiveData<Boolean>
        get() = mIsLeftToolbarOpenLiveData
    private val mIsLeftToolbarOpenLiveData = MutableLiveData<Boolean>().apply { value = false }

    fun setLeftToolbarType(leftToolbarType: LeftToolbarType) {
        mLeftToolbarTypeLiveData.postValue(leftToolbarType)
    }

    fun setIsLeftToolbarOpen(open: Boolean) {
        mIsLeftToolbarOpenLiveData.postValue(open)
    }

    val password: String
        get() = readerModel.password

    enum class OpenFileResult {
        SUCCESS, FAILED, PASSWORD_PROTECTED
    }

    @JvmOverloads
    fun openPdfFile(context: Context, uri: Uri, password: String, onRequestPassword: Runnable, type: String? = null): OpenFileResult {
        if (!isVerified) {
            if (!verifyLicense(context)) {
                return OpenFileResult.FAILED
            }
            isVerified = true
        }
        return openPdfFileImp(context, uri, password, onRequestPassword, type).apply{
            isOpenedFileLiveData.postValue(this == OpenFileResult.SUCCESS)
        }
    }

    private fun openPdfFileImp(context: Context, uri: Uri, password: String, requestPassword: Runnable, type: String?): OpenFileResult {
        file = File(uri.path)
        val factory = KMPDFFactory.open(context, uri, type) ?: return OpenFileResult.FAILED
        readerModel.initKMPDFFactory(factory, uri.path, password)
        kmpdfFactory?.also {
            fileNameLiveData.postValue(it.fileName)
            if (it.needPassWord()) {
                if (!it.authenticatePassword(password)) {
                    requestPassword.run()
                    return OpenFileResult.PASSWORD_PROTECTED
                }
            }
            if (it.init()) {
                return OpenFileResult.SUCCESS
            }
            return OpenFileResult.FAILED
        }
        return OpenFileResult.FAILED
    }

    init {
        readerModel.register()
    }

    override fun onCleared() {
        readerModel.unregister()
        super.onCleared()
    }

    fun copySelection(): Boolean {
        return kmpdfDocumentController?.copySelection() ?: false
    }

    fun onClickCopyBtn() {
        if (annotationModeLiveData.value != AnnotationMode.None) stopAnnotationMode()
        if (isCopyModeLiveData.value == true) {
            stopCopyTextMode()
        } else {
            startCopyTextMode()
        }
    }

    fun onClickHighlightBtn() {
        if (isCopyModeLiveData.value == true) stopCopyTextMode()
        if (annotationModeLiveData.value == AnnotationMode.Highlight) {
            stopAnnotationMode()
        } else {
            startHighLightEditMode()
        }
    }

    fun onLongClickHighlightBtn() {
        if (isCopyModeLiveData.value == true) stopCopyTextMode()
        startHighLightEditMode()
    }

    fun onClickStrikeBtn() {
        if (isCopyModeLiveData.value == true) stopCopyTextMode()
        if (annotationModeLiveData.value == AnnotationMode.Strike) {
            stopAnnotationMode()
        } else {
            startStrikeOutEditMode()
        }
    }

    fun onLongClickStrikeBtn() {
        if (isCopyModeLiveData.value == true) stopCopyTextMode()
        startStrikeOutEditMode()
    }

    fun onClickUnderlineBtn() {
        if (isCopyModeLiveData.value == true) stopCopyTextMode()
        if (annotationModeLiveData.value == AnnotationMode.Underline) {
            stopAnnotationMode()
        } else {
            startUnderLineEditMode()
        }
    }

    fun onLongClickUnderlineBtn() {
        if (isCopyModeLiveData.value == true) stopCopyTextMode()
        startUnderLineEditMode()
    }

    fun onClickInkBtn() {
        if (isCopyModeLiveData.value == true) stopCopyTextMode()
        if (annotationModeLiveData.value == AnnotationMode.Ink) {
            stopAnnotationMode()
        } else {
            startInkEditMode()
        }
    }

    fun onLongClickInkBtn() {
        if (isCopyModeLiveData.value == true) stopCopyTextMode()
        startInkEditMode()
    }

    private fun startCopyTextMode() {
        kmpdfDocumentController?.startCopyText()
        isCopyModeLiveData.postValue(true)
    }

    private fun stopCopyTextMode() {
        kmpdfDocumentController?.stopCopyText()
        isCopyModeLiveData.postValue(false)
    }

    fun setHighLightAttributes(annotationAttribute: AnnotationAttribute) {
        highLightAttributeLiveData.postValue(annotationAttribute)
        setHighLightAttributesImp(annotationAttribute)
    }

    private fun setHighLightAttributesImp(annotationAttribute: AnnotationAttribute) {
        kmpdfFactory?.setAnnotationAttribute(KMPDFHighlightAnnotationBean("", annotationAttribute.color, annotationAttribute.alpha))
        kmpdfFactory?.annotConfig?.apply {
            markerPenColor_hightlight = annotationAttribute.color
            markerPenAlpha_hightlight = annotationAttribute.alpha
        }
    }

    private fun startHighLightEditMode() {
        kmpdfFactory?.setAnnotationEditMode(KMPDFAnnotationBean.AnnotationType.HIGH_LIGHT)
        annotationModeLiveData.postValue(AnnotationMode.Highlight)
    }

    fun setStrikeOutAttributes(annotationAttribute: AnnotationAttribute) {
        strikeAttributeLiveData.postValue(annotationAttribute)
        setStrikeOutAttributesImp(annotationAttribute)
    }

    private fun setStrikeOutAttributesImp(annotationAttribute: AnnotationAttribute) {
        kmpdfFactory?.setAnnotationAttribute(KMPDFStrikeoutAnnotationBean("",annotationAttribute.color, annotationAttribute.alpha))
        kmpdfFactory?.annotConfig?.apply {
            markerPenColor_strikeout = annotationAttribute.color
            markerPenAlpha_strikeout = annotationAttribute.alpha
        }
    }

    private fun startStrikeOutEditMode() {
        kmpdfFactory?.setAnnotationEditMode(KMPDFAnnotationBean.AnnotationType.STRIKE_OUT)
        annotationModeLiveData.postValue(AnnotationMode.Strike)
    }

    fun setUnderLineAttributes(annotationAttribute: AnnotationAttribute) {
        underLineAttributeLiveData.postValue(annotationAttribute)
        setUnderLineAttributesImp(annotationAttribute)
    }

    private fun setUnderLineAttributesImp(annotationAttribute: AnnotationAttribute) {
        kmpdfFactory?.setAnnotationAttribute(KMPDFUnderlineAnnotationBean("", annotationAttribute.color, annotationAttribute.alpha))
        kmpdfFactory?.annotConfig?.apply {
            markerPenColor_underline = annotationAttribute.color
            markerPenAlpha_underline = annotationAttribute.alpha
        }
    }

    private fun startUnderLineEditMode() {
        kmpdfFactory?.setAnnotationEditMode(KMPDFAnnotationBean.AnnotationType.UNDER_LINE)
        annotationModeLiveData.postValue(AnnotationMode.Underline)
    }

    fun setInkAttributes(inkAttribute: InkAttribute) {
        inkAttributeLiveData.postValue(inkAttribute)
        setInkAttributesImp(inkAttribute)
    }

    fun setInkAttributesImp(inkAttribute: InkAttribute) {
        kmpdfFactory?.apply {
            setAnnotationAttribute(KMPDFInkAnnotationBean("", inkAttribute.color, inkAttribute.width, inkAttribute.alpha))
            annotConfig?.apply {
                markerPenColor_ink = inkAttribute.color
                markerPenAlpha_ink = inkAttribute.alpha
                markerPenSize_ink = inkAttribute.width
            }
        }
    }

    private fun startInkEditMode() {
        kmpdfFactory?.setAnnotationEditMode(KMPDFAnnotationBean.AnnotationType.INK)
        annotationModeLiveData.postValue(AnnotationMode.Ink)
    }

    fun stopAnnotationMode() {
        kmpdfFactory?.setAnnotationEditMode(KMPDFAnnotationBean.AnnotationType.NULL)
        annotationModeLiveData.postValue(AnnotationMode.None)
    }

    fun setReaderView(readerView: KMPDFReaderView) {
        val isFirst = kmpdfFactory?.readerView == null
        kmpdfFactory?.readerView = readerView
        readerModel.initKMPDFDocumentController()

        /** init annotation color **/
        highLightAttributeLiveData.value?.also { setHighLightAttributesImp(it) }
        strikeAttributeLiveData.value?.also { setStrikeOutAttributesImp(it) }
        underLineAttributeLiveData.value?.also { setUnderLineAttributesImp(it) }
        inkAttributeLiveData.value?.also { setInkAttributesImp(it) }

        updateViewDirection()

        kmpdfFactory?.kmpdfAddAnnotCallback = object : KMPDFAddAnnotCallback {

            override fun onSaveAnnotFinished(type: Annotation.Type, result: Boolean, message: String) {
                println("KMPDFAddAnnotCallback::onSaveAnnotFinished")
            }

            override fun onAttachAnnotWidgetFinished(type: Annotation.Type) {
                println("KMPDFAddAnnotCallback::onAttachAnnotWidgetFinished")
                val mode = when (type) {
                    Annotation.Type.FREETEXT -> KMPDFAnnotEditMode.Mode.FREETEXT_MODIFY
                    Annotation.Type.STAMP -> KMPDFAnnotEditMode.Mode.STAMP_MODIFY
                    Annotation.Type.CIRCLE, Annotation.Type.SQUARE, Annotation.Type.LINE -> KMPDFAnnotEditMode.Mode.SHAPE_MODIFY
                    else -> KMPDFAnnotEditMode.Mode.NULL
                }
                if (mode != KMPDFAnnotEditMode.Mode.NULL) {
                    kmpdfFactory?.kmpdfAnnotEditMode?.pdfAnnotEditMode = mode
                }
            }
        }

        kmpdfFactory?.kmpdfAnnotEditModeChangeListener = KMPDFAnnotEditModeChangeListener {
            annotationEitModeLiveData.postValue(it)
        }

        setLongPressContextMenuActions()
        setSignatureContextMenuActions()
        setStampContextMenuActions()
        setShapeContextMenuActions()
        setInkMenuActions()
        setMarkerUpMenuActions()

        if (!isFirst) {
            restoreStateBeforeDestroy()
        }
    }

    private fun setLongPressContextMenuActions() {
        val item = KMPDFMenuItem()
        item.annotType = KMPDFMenuItem.AnnotType.LONG_PRESS
        item.menu_resId = R.menu.context_menu_longpress
        item.menuCallbacks.add(MenuItemCallback { view, annotType ->
            (kmpdfFactory?.getController(KMPDFFactory.ControllerType.LONGCLICK) as KMPDFLongPressCreateAnnotController).longPress_Paste()
            annotationEitModeLiveData.postValue(KMPDFAnnotEditMode.Mode.FREETEXT_MODIFY)
            return@MenuItemCallback true
        })
        kmpdfFactory?.setAnnotationContextMenu(item)
    }

    private fun setSignatureContextMenuActions() {
        val item = KMPDFMenuItem()
        item.annotType = KMPDFMenuItem.AnnotType.SIGNATURE
        item.menu_resId = R.menu.context_menu_signature
        item.menuCallbacks.add(MenuItemCallback { view, annotType ->
            (kmpdfFactory?.getController(KMPDFFactory.ControllerType.SIGNATURE) as KMPDFSignatureController).deleteSignatureAnnotView()
            return@MenuItemCallback true
        })
        item.menuCallbacks.add(MenuItemCallback { view, annotType ->
            (kmpdfFactory?.getController(KMPDFFactory.ControllerType.SIGNATURE) as KMPDFSignatureController).saveSignatureAnnot()
            return@MenuItemCallback true
        })
        kmpdfFactory?.setAnnotationContextMenu(item)
    }

    private fun setStampContextMenuActions() {
        val item = KMPDFMenuItem()
        item.annotType = KMPDFMenuItem.AnnotType.STAMP
        item.menu_resId = R.menu.context_menu_normal
        item.menuCallbacks.add(MenuItemCallback { view, annotType ->
            (kmpdfFactory?.getController(KMPDFFactory.ControllerType.STAMP) as KMPDFStampController).deleteStampAnnotView()
            return@MenuItemCallback true
        })
        kmpdfFactory?.setAnnotationContextMenu(item)
    }

    private fun setShapeContextMenuActions() {
        val item = KMPDFMenuItem()
        item.annotType = KMPDFMenuItem.AnnotType.LINE
        item.menu_resId = R.menu.context_menu_normal
        item.menuCallbacks.add(MenuItemCallback { view, annotType ->
            (kmpdfFactory?.getController(KMPDFFactory.ControllerType.SHAPE) as KMPDFShapeAnnotController).deleteShapeAnnotView()
            return@MenuItemCallback true
        })
        kmpdfFactory?.setAnnotationContextMenu(item)
    }

    private fun setInkMenuActions() {
        val item = KMPDFMenuItem()
        item.annotType = KMPDFMenuItem.AnnotType.INK
        item.menu_resId = R.menu.context_menu_normal
        item.menuCallbacks.add(MenuItemCallback { _, _ ->
            kmpdfFactory?.let {
                val controller = it.getController(KMPDFFactory.ControllerType.INK) as KMPDFInkController
                controller.deleteInkAnnotView()
                return@MenuItemCallback true
            }
            return@MenuItemCallback false
        })
        kmpdfFactory?.setAnnotationContextMenu(item)
    }

    private fun setMarkerUpMenuActions() {
        val item = KMPDFMenuItem()
        /** Just set HIGH_LIGHT then highlight, strike, underline will be triggered. **/
        /** WTF !!!!!!!!!!! **/
        item.annotType = KMPDFMenuItem.AnnotType.HIGH_LIGHT
        item.menu_resId = R.menu.context_menu_normal
        item.menuCallbacks.add(MenuItemCallback { _, _ ->
            kmpdfFactory?.let {
                val controller = it.getController(KMPDFFactory.ControllerType.MARKER_UP) as KMPDFMarkupController
                controller.deleteMarkupAnnotView()
                return@MenuItemCallback true
            }
            return@MenuItemCallback false
        })
        kmpdfFactory?.setAnnotationContextMenu(item)
    }

    fun setTextBoxContextMenuActions(listener: TextBoxContextMenuActionListener) {
        val item = KMPDFMenuItem()
        item.annotType = KMPDFMenuItem.AnnotType.FREETEXT
        item.menu_resId = R.menu.context_menu_textbox
        item.menuCallbacks.add(MenuItemCallback { view, annotType ->
            return@MenuItemCallback listener.onDelete()
        })
        item.menuCallbacks.add(MenuItemCallback { view, annotType ->
            return@MenuItemCallback listener.onEditStyle()
        })
        item.menuCallbacks.add(MenuItemCallback { view, annotType ->
            return@MenuItemCallback listener.onEditText()
        })
        item.menuCallbacks.add(MenuItemCallback { view, annotType ->
            return@MenuItemCallback listener.onCopy()
        })
        kmpdfFactory?.setAnnotationContextMenu(item)
    }

    private fun restoreStateBeforeDestroy() {
        if (isCopyModeLiveData.value == true) {
            startCopyTextMode()
        } else {
            annotationModeLiveData.value?.also {
                val annotationEditMode = when (it) {
                    AnnotationMode.None -> KMPDFAnnotationBean.AnnotationType.NULL
                    AnnotationMode.Highlight -> KMPDFAnnotationBean.AnnotationType.HIGH_LIGHT
                    AnnotationMode.Strike -> KMPDFAnnotationBean.AnnotationType.STRIKE_OUT
                    AnnotationMode.Underline -> KMPDFAnnotationBean.AnnotationType.UNDER_LINE
                    AnnotationMode.Ink -> KMPDFAnnotationBean.AnnotationType.INK
                }
                kmpdfFactory?.setAnnotationEditMode(annotationEditMode)
                annotationModeLiveData.postValue(it)
            }
        }
    }

    fun saveModifyingAnnotation() {
        kmpdfFactory?.setAnnotationEditMode(KMPDFAnnotationBean.AnnotationType.NULL)
    }

    fun clearSelection() {
        kmpdfFactory?.setAnnotationEditMode(KMPDFAnnotationBean.AnnotationType.NULL)
        kmpdfFactory?.kmpdfAnnotEditMode?.pdfAnnotEditMode = KMPDFAnnotEditMode.Mode.NULL
        annotationEitModeLiveData.postValue(KMPDFAnnotEditMode.Mode.NULL)
    }

    fun deleteSelectedTextBox() {
        (kmpdfFactory?.getController(KMPDFFactory.ControllerType.FREETEXT) as KMPDFFreeTextController).deleteFreeTextAnnotView()
    }

    fun editSelectedTextBoxStyle() {
        (kmpdfFactory?.getController(KMPDFFactory.ControllerType.FREETEXT) as KMPDFFreeTextController).setCurrentFreeTextViewEditMode(0)
    }

    fun editSelectedTextBoxText() {
        (kmpdfFactory?.getController(KMPDFFactory.ControllerType.FREETEXT) as KMPDFFreeTextController).setCurrentFreeTextViewEditMode(1)
    }

    fun copySelectedTextBox() {
        (kmpdfFactory?.getController(KMPDFFactory.ControllerType.FREETEXT) as KMPDFFreeTextController).copyFreeTextContent()
    }

    fun setPageIndex(pageIndex: Int){
        mPageIndexLiveData.value = pageIndex
    }

    fun addBookmark(title: String) {
        pageIndexLiveData.value?.let {
            kmpdfDocumentController?.addBookmark(title, it)
            setBookmarkDisplay(it)
        }
    }

    fun deleteBookmark() {
        pageIndexLiveData.value?.let {
            kmpdfDocumentController?.deleteBookmarks(it)
            setBookmarkDisplay(it)
        }
    }

    fun setBookmarkDisplay(pageIndex: Int) {
        kmpdfDocumentController?.let {
            var isPageInBookmarks = false
            it.bookmarks?.let {
                for (bookmark in it) {
                    if (bookmark.pageNum == pageIndex) {
                        isPageInBookmarks = true
                        break
                    }
                }
            }
            mIsPageInBookmarksLiveData.value = isPageInBookmarks
        }
    }

    fun clearSignature() {
        readerModel.kmpdfSignatureController?.deleteAllSign()
    }

    fun temporarySave() {
        //  TODO this workaround should be removed in the future
        //  workaround: password-protected pdf is not editable
        if (kmpdfFactory?.needPassWord() == true) return
        kmpdfDocumentController?.temporarySave()
    }

    fun transferReaderModel(){
        PdfThumbViewModel.tempReaderModel = readerModel
    }

    private fun verifyLicense(context: Context): Boolean {
        val errorCode = KMPDFFactory.verifyLicense(context, pdfSdkLicense, pdfSdkRsaMsg)
        return errorCode == 0
    }

    private fun updateViewDirection() {
        kmpdfDocumentController?.pdfViewMode = viewDirection.mode
        kmpdfDocumentController?.refresh(false)
    }

    private fun updateReadMode() {
        when (readMode) {
            ReadMode.READ_MODE_DAY, ReadMode.READ_MODE_NIGHT, ReadMode.READ_MODE_SOFT -> kmpdfDocumentController?.readMode = readMode.mode
            ReadMode.MODE_CHROME_WHITE -> kmpdfDocumentController?.setReadMode(204, 197, 179)
            ReadMode.MODE_ETON_BLUE -> kmpdfDocumentController?.setReadMode(200, 236, 205)
            ReadMode.MODE_WHITE_LILAC -> kmpdfDocumentController?.setReadMode(232, 232, 232)
        }
        kmpdfDocumentController?.refresh(false)
        kmpdfFactory?.readerView?.context?.also {
            val colorResId = when (readMode) {
                ReadMode.READ_MODE_DAY -> R.color.color_bolder
                ReadMode.READ_MODE_NIGHT -> R.color.black_38
                else -> R.color.color_divier
            }
            kmpdfFactory?.readerView?.setBackgroundColor(ContextCompat.getColor(it, colorResId))
        }
    }

    private fun updateCrop() {
        kmpdfDocumentController?.apply {
            cropMode = isCrop
            refresh(false)
        }
    }

    fun getPageText(pageIndex: Int): List<String> {
        val dc = kmpdfDocumentController ?: return Collections.emptyList()
        val lines = ArrayList<String>()
        dc.textLines(pageIndex).forEach {
            val s = StringBuilder()
            it.forEach { textWord ->
                s.append(textWord.w)
                s.append(" ")
            }
            lines.add(s.toString())
        }
        return lines
    }

    fun setTextBoxAttribute(attr: TextBoxAttribute, modify: Boolean = false) {

        val kmpdfFreetextAnnotationBean = KMPDFFreetextAnnotationBean("", attr.textColor, attr.textSize, 255, "Courier", attr.isBold, attr.isItalic)
        kmpdfFactory?.setAnnotationAttribute(kmpdfFreetextAnnotationBean)
        if (!modify) {
            kmpdfFactory?.setAnnotationEditMode(KMPDFAnnotationBean.AnnotationType.FREETEXT)
        }
    }

    fun setSignatureAttribute(attr: SignatureAttribute) {

        val kmpdfSignatureAnnotationBean = KMPDFSignatureAnnotationBean("", attr.path, KMPDFSignatureController.OnSignImageCreateListener {
            println("onSignImageCreated")
        })
        kmpdfFactory?.setAnnotationAttribute(kmpdfSignatureAnnotationBean)
        kmpdfFactory?.setAnnotationEditMode(KMPDFAnnotationBean.AnnotationType.SIGNATURE)
    }

    fun setStampAttribute(attr: StampAttribute) {

        val kmpdfStampAnnotationBean = when (attr.isStandardStamp()) {
            true -> KMPDFStampAnnotationBean("", KMPDFStampAnnotationBean.StampType.STANDARD, KMPDFStampAnnotationBean.StandardStamp(attr.resId))
            false -> KMPDFStampAnnotationBean("", KMPDFStampAnnotationBean.StampType.TEXT, KMPDFStampAnnotationBean.TextStamp(attr.config))
        }
        kmpdfFactory?.setAnnotationAttribute(kmpdfStampAnnotationBean)
        kmpdfFactory?.setAnnotationEditMode(KMPDFAnnotationBean.AnnotationType.STAMP)
    }

    fun setShapeAttribute(attr: ShapeAttribute) {

        val kmpdfShapeAnnotationBean = when (attr.shapeType) {
            AnnotConfig.ShapeAnnotationType.LINE -> KMPDFLineAnnotationBean("", attr.lineColor, attr.lineWidth, attr.lineAlpha)
            AnnotConfig.ShapeAnnotationType.ARROW -> KMPDFArrowAnnotationBean("", attr.lineColor, attr.lineWidth, attr.lineAlpha)
            AnnotConfig.ShapeAnnotationType.CIRCLE -> KMPDFCircleAnnotationBean("", attr.lineColor, attr.lineWidth, attr.lineAlpha, attr.fillColor, attr.fillAlpha)
            AnnotConfig.ShapeAnnotationType.SQUARE -> KMPDFSquareAnnotationBean("", attr.lineColor, attr.lineWidth, attr.lineAlpha, attr.fillColor, attr.fillAlpha)
        }
        kmpdfFactory?.setAnnotationAttribute(kmpdfShapeAnnotationBean)
        kmpdfFactory?.setAnnotationEditMode(kmpdfShapeAnnotationBean.type)
    }

    val pdfInfoHandler = object : PdfInfoHandler {
        override fun getOpenPdfFilename(): String {
            return kmpdfFactory?.fileName ?: ""
        }

        override fun getPdfPageCount(isNativeRefresh: Boolean): Int {
            return kmpdfDocumentController?.getDocumentPageCount(isNativeRefresh) ?: 0
        }

        override fun getCurrentPage(): Int {
            return kmpdfDocumentController?.currentPageNum ?: 0
        }

        override fun setCurrentPage(page: Int): Boolean {
            return kmpdfDocumentController?.gotoPage(page) ?: false
        }

        override fun textLines(page: Int): Array<Array<TextWord>> {
            return kmpdfDocumentController?.textLines(page) ?: arrayOf()
        }

        override fun getPageChars(page: Int): Array<Array<Array<Array<TextChar>>>> {
            return kmpdfDocumentController?.getPageChars(page) ?: arrayOf()
        }
    }

    val thumbnailHandler = object : ThumbnailHandler {
        override fun getPdfBitmap(position: Int, picWidth: Int, mode: Int, isDrawAnnot: Boolean): Bitmap {
            return kmpdfDocumentController?.covertPDFToBitmap(position, picWidth, mode, isDrawAnnot) ?: Bitmap.createBitmap(0, 0, Bitmap.Config.ARGB_4444)
        }
    }

    val bookmarkHandler = object : BookmarkHandler {
        override fun getBookmarks(): Array<Bookmark> {
            return kmpdfDocumentController?.bookmarks ?: arrayOf()
        }
    }

    val outlineHandler = object : OutlineHandler {
        override fun getOutline(): Array<OutlineItem> {
            return kmpdfDocumentController?.outline ?: arrayOf()
        }
    }

    val searchHandler = object : SearchHandler {
        override fun searchPage(page: Int, keyword: String): Array<RectF> {
            return kmpdfDocumentController?.searchPage(page, keyword) ?: arrayOf()
        }

        override fun cleanPreviousSearchResults(keyword: String): Boolean {
            return kmpdfDocumentController?.cleanPreviousSearchResults(keyword) ?: false
        }

        override fun setSearchResult(page: Int, keyword: String, rectArray: Array<RectF>): Boolean {
            return kmpdfDocumentController?.setSearchResult(keyword, page, rectArray) ?: false
        }

        override fun stopSearchKeyWord(): Boolean {
            return kmpdfDocumentController?.stopSearchKeyWord() ?: false
        }
    }
}