package com.base.pdfreaderallpdfreader.utils

import android.content.Context
import android.graphics.Bitmap
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.net.Uri
import com.base.pdfreaderallpdfreader.utils.UriUtils.readFileToByteArray
import com.tom_roush.pdfbox.pdmodel.PDDocument
import com.tom_roush.pdfbox.pdmodel.PDPage
import com.tom_roush.pdfbox.pdmodel.PDPageContentStream
import com.tom_roush.pdfbox.pdmodel.common.PDRectangle
import com.tom_roush.pdfbox.pdmodel.encryption.AccessPermission
import com.tom_roush.pdfbox.pdmodel.encryption.StandardProtectionPolicy
import com.tom_roush.pdfbox.pdmodel.graphics.image.PDImageXObject
import com.tom_roush.pdfbox.rendering.ImageType
import com.tom_roush.pdfbox.rendering.PDFRenderer
import com.tom_roush.pdfbox.rendering.RenderDestination
import java.io.File
import java.io.IOException


object PdfBoxUtils {

    private val TAG = "PdfUtils"

    fun getNumberOfPages(context: Context, filePath: String, password: String? = null, uri: String? = null): Int {
        val document = context.loadPDDocument(path = filePath, password, uri)
        return document.numberOfPages
    }


    fun getPdfDrawablePage(
        context: Context,
        filePath: String,
        password: String? = null,
        uri: String? = null,
        pageIndex: Int,
        scale: Float = 1f,
    ): Drawable {
        val document = context.loadPDDocument(filePath, password, uri)
        val renderer = PDFRenderer(document)

        val bitmap: Bitmap = renderer.renderImage(pageIndex, scale, ImageType.RGB, RenderDestination.EXPORT)

        val drawable = BitmapDrawable(context.resources, bitmap)

        return drawable
    }


    fun Context.checkPdfEncryption(filePath: String = "", uri: String? = null): Int {
        var state = 0
        var pdfDocument: PDDocument? = null
        try {
            pdfDocument = loadPDDocument(filePath, null, uri)
            pdfDocument.use { document ->
                if (document.isEncrypted) {
                    println("The PDF is encrypted.")
                    val ap = document.getCurrentAccessPermission()
                    if (ap.canExtractContent()) {
                        println("You are allowed to extract content.")
                    } else {
                        state = 1
                        println("You are not allowed to extract content.")
                    }
                    if (ap.canPrint()) {
                        println("You are allowed to print the document.")
                    } else {
                        println("You are not allowed to print the document.")
                        state = 1
                    }
                } else {
                    println("The PDF is not encrypted.")
                    state = 0
                }
            }
        } catch (e: IOException) {
            e.printStackTrace()
            state = 1
        } finally {
            pdfDocument?.close()
        }
        return state
    }


    fun setPassword(
        sourceFilePath: String,
        userPassword: String,
        ownerPassword: String
    ): Boolean {

        try {
            PDDocument.load(File(sourceFilePath)).use { document ->
                val ap = AccessPermission()
                ap.setCanPrint(false)
                ap.setCanModify(false)
                ap.setCanExtractContent(false)
                ap.setCanExtractForAccessibility(false)
                ap.setCanFillInForm(false)
                val spp = StandardProtectionPolicy(userPassword, ownerPassword, ap)
                document.protect(spp)
                document.save(File(sourceFilePath))
                LogEx.logDebug(TAG, "setPassword finish")
            }
        } catch (e: Exception) {
            LogEx.logDebug(TAG, "setPassword Exception ${e.printStackTrace()}")
            e.printStackTrace()
            return false
        }
        return true
    }

    fun clearPassword(filePath: String, password: String) {
        try {
            PDDocument.load(File(filePath), password).use { document ->
                if (document.isEncrypted) {
                    val ap: AccessPermission = document.getCurrentAccessPermission()
                    if (ap.isOwnerPermission) {
                        // 创建一个新的保护策略，不设置密码
                        val spp = StandardProtectionPolicy(
                            "", "",
                            AccessPermission.getOwnerAccessPermission()
                        )
                        document.protect(spp)
                    }
                }
                // 保存PDF文件到新的位置，没有密码保护
                document.save(File(filePath))
            }
        } catch (e: IOException) {
            e.printStackTrace()
        }
    }


    fun Context.checkPwd(
        filePath: String,
        password: String,
        uri: String? = null
    ): Boolean {
        try {
            val pdfDocument = loadPDDocument(filePath, password, uri)
            // 尝试使用提供的密码加载PDF文件
            pdfDocument.use { document ->
                // 如果没有抛出异常，说明密码正确
                return true
            }
        } catch (e: Exception) {
            // 加载文件时，如果密码保护策略异常，密码可能错误
            println("Incorrect password or restricted permissions.")
        } catch (e: IOException) {
            // 其他I/O异常处理
            println("An I/O error occurred: " + e.message)
        }
        return false
    }

    private fun Context.loadPDDocument(path: String, password: String?, uri: String? = null): PDDocument {
        return if (uri == null) {
            if (password == null) {
                PDDocument.load(File(path))
            } else {
                PDDocument.load(File(path), password)
            }
        } else {
            if (password == null) {
                PDDocument.load(readFileToByteArray(this, Uri.parse(uri)) ?: byteArrayOf())

            } else {
                PDDocument.load(readFileToByteArray(this, Uri.parse(uri)) ?: byteArrayOf(), password)
            }
        }
    }


    fun saveNewPdf(imagePath: String, savePath: String) {
        try {
            PDDocument().use { document ->
                // 添加一个页面
                val page = PDPage(PDRectangle.A4)
                document.addPage(page)

                // 加载图片
                val image = PDImageXObject.createFromFile(imagePath, document)

                // 计算图片在页面中的位置和尺寸
                val x = (PDRectangle.A4.width - image.width) / 2
                val y = (PDRectangle.A4.height - image.height) / 2
                PDPageContentStream(document, page).use { contentStream ->
                    contentStream.drawImage(
                        image,
                        x,
                        y,
                        image.width.toFloat(),
                        image.height.toFloat()
                    )
                }

                // 保存PDF文档
                document.save(savePath)
            }
        } catch (e: IOException) {
            e.printStackTrace()
        }
    }

}