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.RectF
import android.net.Uri
import com.kdanmobile.kmpdfkit.annotation.bean.*
import com.kdanmobile.kmpdfkit.globaldata.AnnotConfig
import com.kdanmobile.kmpdfkit.globaldata.Config
import com.kdanmobile.kmpdfkit.manager.KMPDFFactory
import com.kdanmobile.kmpdfkit.manager.controller.KMPDFDocumentController
import com.kdanmobile.kmpdfkit.pdfcommon.*
import com.kdanmobile.reader.screen.data.ShapeAttribute
import com.kdanmobile.reader.screen.data.StampAttribute
import com.kdanmobile.reader.screen.data.TextBoxAttribute
import com.kdanmobile.reader.screen.handler.*

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)
    }

    var viewDirection = ViewDirection.VerticalSinglePageContinues
        set(value) {
            field = value
            updateViewDirection()
        }
    var isCrop = false
        set(value) {
            field = value
            updateCrop()
        }
    var isCopyMode = false
        private set

    private var isVerified = false

    private var kmpdfFactory: KMPDFFactory? = null
    private var kmpdfDocumentController: KMPDFDocumentController? = null
    val isOpenedFileLiveData = MutableLiveData<Boolean>().apply { value = false }
    val fileNameLiveData = MutableLiveData<String>()

    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 }

    @JvmOverloads
    fun openPdfFile(context: Context, uri: Uri, type: String? = null): Boolean {
        if (!isVerified) {
            if (!verifyLicense(context)) {
                return false
            }
        }
        return openPdfFIleImp(context, uri, type).apply{
            isOpenedFileLiveData.postValue(this)
        }
    }

    private fun openPdfFIleImp(context: Context, uri: Uri, type: String?): Boolean {
        val factory = KMPDFFactory.open(context, uri, type) ?: return false
        kmpdfFactory = factory
        kmpdfFactory?.also {
            fileNameLiveData.postValue(it.fileName)
            return when {
                it.needPassWord() -> {
                    false
                }
                it.init() -> {
                    true
                }
                else -> {
                    false
                }
            }
        }
        return false
    }

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

    fun startCopyTextMode() {
        kmpdfDocumentController?.startCopyText()
        isCopyMode = true
    }

    fun stopCopyTextMode() {
        kmpdfDocumentController?.stopCopyText()
        isCopyMode = false
    }

    fun setHighLightAttributes(color: Int, alpha: Int) {
        kmpdfFactory?.setAnnotationAttribute(KMPDFHighlightAnnotationBean("", color, alpha))
        kmpdfFactory?.annotConfig?.apply {
            markerPenColor_hightlight = color
            markerPenAlpha_hightlight = alpha
        }
    }

    fun startHighLightEditMode() {
        kmpdfFactory?.setAnnotationEditMode(KMPDFAnnotationBean.AnnotationType.HIGH_LIGHT)
    }

    fun setStrikeOutAttributes(color: Int, alpha: Int) {
        kmpdfFactory?.setAnnotationAttribute(KMPDFStrikeoutAnnotationBean("", color, alpha))
        kmpdfFactory?.annotConfig?.apply {
            markerPenColor_strikeout = color
            markerPenAlpha_strikeout = alpha
        }
    }

    fun startStrikeOutEditMode() {
        kmpdfFactory?.setAnnotationEditMode(KMPDFAnnotationBean.AnnotationType.STRIKE_OUT)
    }

    fun setUnderLineAttributes(color: Int, alpha: Int) {
        kmpdfFactory?.setAnnotationAttribute(KMPDFUnderlineAnnotationBean("", color, alpha))
        kmpdfFactory?.annotConfig?.apply {
            markerPenColor_underline = color
            markerPenAlpha_underline = alpha
        }
    }

    fun startUnderLineEditMode() {
        kmpdfFactory?.setAnnotationEditMode(KMPDFAnnotationBean.AnnotationType.UNDER_LINE)
    }

    fun setInkAttributes(color: Int, alpha: Int, width: Float) {
        kmpdfFactory?.apply {
            setAnnotationAttribute(KMPDFInkAnnotationBean("", color, width, alpha))
            annotConfig?.apply {
                markerPenColor_ink = color
                markerPenAlpha_ink = alpha
                markerPenSize_ink = width
            }
        }
    }

    fun startInkEditMode() {
        kmpdfFactory?.setAnnotationEditMode(KMPDFAnnotationBean.AnnotationType.INK)
    }

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

    fun setReaderView(readerView: KMPDFReaderView) {
        kmpdfFactory?.readerView = readerView
        kmpdfDocumentController = kmpdfFactory?.getController(KMPDFFactory.ControllerType.DOCUMENT) as KMPDFDocumentController
        updateViewDirection()
    }

    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
        }
    }

    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 updateCrop() {
        kmpdfDocumentController?.apply {
            cropMode = isCrop
            refresh(false)
        }
    }

    fun setTextBoxAttribute(attr: TextBoxAttribute) {

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

    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.rect, 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(): Int {
            return kmpdfDocumentController?.getDocumentPageCount(false) ?: 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()
        }
    }

    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 cleanPreviousSearchResults(page: Int, keyword: String, rectArray: Array<RectF>): Boolean {
            return kmpdfDocumentController?.setSearchResult(keyword, page, rectArray) ?: false
        }

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