/**
 * 自然写互动课堂智慧黑板端应用软件 V1.0
 *
 * CoursewareLoader.kt - 课件加载与渲染
 *
 * 功能说明：
 * - 多格式课件加载（PPT/PDF/图片）
 * - 课件页面缓存管理
 * - 课件翻页与缩放
 * - 课件标注叠加
 * - 课件预下载与离线访问
 * - 与白板引擎集成
 */

package com.writech.board.engine

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.pdf.PdfRenderer
import android.os.ParcelFileDescriptor
import android.util.Log
import android.util.LruCache
import java.io.File
import java.io.FileOutputStream
import java.net.URL
import java.util.concurrent.*

/**
 * 课件类型
 */
enum class CoursewareType {
    PDF,         /* PDF文档 */
    PPT,         /* PowerPoint演示文稿 */
    IMAGE,       /* 图片（PNG/JPG） */
    IMAGE_SET    /* 图片集（多页图片） */
}

/**
 * 课件信息
 */
data class CoursewareInfo(
    val coursewareId: String,          /* 课件ID */
    val title: String,                 /* 课件标题 */
    val type: CoursewareType,          /* 课件类型 */
    val localPath: String,             /* 本地文件路径 */
    val totalPages: Int,               /* 总页数 */
    val downloadUrl: String = "",      /* 云端下载URL */
    val fileSize: Long = 0,            /* 文件大小 */
    val subject: String = "",          /* 学科 */
    val grade: String = ""             /* 年级 */
)

/**
 * 课件页面数据
 */
data class CoursewarePage(
    val pageIndex: Int,                /* 页码（0开始） */
    val bitmap: Bitmap?,               /* 页面位图 */
    val width: Int,                    /* 原始宽度 */
    val height: Int                    /* 原始高度 */
)

/**
 * 课件加载回调
 */
interface CoursewareLoadListener {
    fun onCoursewareLoaded(info: CoursewareInfo)
    fun onPageReady(page: CoursewarePage)
    fun onLoadProgress(progress: Float)
    fun onLoadError(error: String)
}

/**
 * 课件加载与渲染引擎
 *
 * 支持多种格式课件的加载、缓存和渲染：
 * - PDF: 使用Android PdfRenderer渲染
 * - PPT: 转换为图片后渲染
 * - 图片: 直接BitmapFactory加载
 */
class CoursewareLoader(private val context: Context) {

    companion object {
        private const val TAG = "CoursewareLoader"
        /** 页面缓存最大数量 */
        private const val PAGE_CACHE_SIZE = 10
        /** 渲染目标DPI */
        private const val RENDER_DPI = 300
        /** 课件存储目录 */
        private const val COURSEWARE_DIR = "courseware"
        /** 下载超时（毫秒） */
        private const val DOWNLOAD_TIMEOUT_MS = 60000
    }

    /* ==================== 状态 ==================== */

    /** 当前加载的课件信息 */
    var currentCourseware: CoursewareInfo? = null
        private set

    /** 当前页码 */
    var currentPage: Int = 0
        private set

    /** PDF渲染器 */
    private var pdfRenderer: PdfRenderer? = null
    private var pdfFileDescriptor: ParcelFileDescriptor? = null

    /** 页面位图缓存（LRU） */
    private val pageCache = LruCache<Int, Bitmap>(PAGE_CACHE_SIZE)

    /** 图片集页面路径列表 */
    private val imagePages = mutableListOf<String>()

    /** 事件监听器 */
    private var listener: CoursewareLoadListener? = null

    /** 后台线程池 */
    private val executor: ExecutorService = Executors.newFixedThreadPool(2)

    /**
     * 设置加载监听器
     */
    fun setListener(listener: CoursewareLoadListener) {
        this.listener = listener
    }

    /* ==================== 课件加载 ==================== */

    /**
     * 加载本地课件文件
     * 
     * @param filePath 本地文件路径
     * @param type 课件类型
     */
    fun loadFromFile(filePath: String, type: CoursewareType) {
        executor.submit {
            try {
                Log.i(TAG, "加载课件: $filePath, 类型=$type")

                when (type) {
                    CoursewareType.PDF -> loadPdf(filePath)
                    CoursewareType.IMAGE -> loadSingleImage(filePath)
                    CoursewareType.IMAGE_SET -> loadImageSet(filePath)
                    CoursewareType.PPT -> loadPptAsImages(filePath)
                }
            } catch (e: Exception) {
                Log.e(TAG, "课件加载失败", e)
                listener?.onLoadError("加载失败: ${e.message}")
            }
        }
    }

    /**
     * 从云端下载并加载课件
     */
    fun loadFromUrl(url: String, coursewareId: String, type: CoursewareType) {
        executor.submit {
            try {
                Log.i(TAG, "下载课件: $url")
                listener?.onLoadProgress(0f)

                /* 确定本地存储路径 */
                val localDir = File(context.filesDir, COURSEWARE_DIR)
                if (!localDir.exists()) localDir.mkdirs()

                val extension = when (type) {
                    CoursewareType.PDF -> ".pdf"
                    CoursewareType.PPT -> ".pptx"
                    else -> ".png"
                }
                val localFile = File(localDir, "${coursewareId}$extension")

                /* 如果本地已存在则直接使用 */
                if (localFile.exists() && localFile.length() > 0) {
                    Log.i(TAG, "使用本地缓存: ${localFile.absolutePath}")
                    loadFromFile(localFile.absolutePath, type)
                    return@submit
                }

                /* 下载文件 */
                downloadFile(url, localFile)

                /* 加载下载的文件 */
                loadFromFile(localFile.absolutePath, type)

            } catch (e: Exception) {
                Log.e(TAG, "课件下载失败", e)
                listener?.onLoadError("下载失败: ${e.message}")
            }
        }
    }

    /**
     * 下载文件到本地
     */
    private fun downloadFile(url: String, destFile: File) {
        val connection = URL(url).openConnection()
        connection.connectTimeout = DOWNLOAD_TIMEOUT_MS
        connection.readTimeout = DOWNLOAD_TIMEOUT_MS

        val totalSize = connection.contentLengthLong
        var downloadedSize = 0L

        connection.getInputStream().use { input ->
            FileOutputStream(destFile).use { output ->
                val buffer = ByteArray(8192)
                var bytesRead: Int
                while (input.read(buffer).also { bytesRead = it } != -1) {
                    output.write(buffer, 0, bytesRead)
                    downloadedSize += bytesRead

                    if (totalSize > 0) {
                        val progress = downloadedSize.toFloat() / totalSize
                        listener?.onLoadProgress(progress)
                    }
                }
            }
        }

        Log.i(TAG, "文件下载完成: ${destFile.absolutePath}, 大小=${downloadedSize / 1024}KB")
    }

    /* ==================== PDF加载 ==================== */

    /**
     * 加载PDF文件
     */
    private fun loadPdf(filePath: String) {
        closePdfRenderer()

        val file = File(filePath)
        pdfFileDescriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY)
        pdfRenderer = PdfRenderer(pdfFileDescriptor!!)

        val pageCount = pdfRenderer!!.pageCount
        currentCourseware = CoursewareInfo(
            coursewareId = file.nameWithoutExtension,
            title = file.nameWithoutExtension,
            type = CoursewareType.PDF,
            localPath = filePath,
            totalPages = pageCount
        )
        currentPage = 0

        Log.i(TAG, "PDF加载成功: ${file.name}, ${pageCount}页")
        listener?.onCoursewareLoaded(currentCourseware!!)

        /* 渲染第一页 */
        renderPdfPage(0)
    }

    /**
     * 渲染PDF指定页面为Bitmap
     */
    private fun renderPdfPage(pageIndex: Int) {
        val renderer = pdfRenderer ?: return
        if (pageIndex < 0 || pageIndex >= renderer.pageCount) return

        /* 先检查缓存 */
        pageCache.get(pageIndex)?.let { cached ->
            val page = CoursewarePage(pageIndex, cached, cached.width, cached.height)
            listener?.onPageReady(page)
            return
        }

        /* 渲染新页面 */
        val pdfPage = renderer.openPage(pageIndex)

        /* 计算渲染尺寸（基于DPI） */
        val scale = RENDER_DPI.toFloat() / 72f
        val width = (pdfPage.width * scale).toInt()
        val height = (pdfPage.height * scale).toInt()

        val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
        pdfPage.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
        pdfPage.close()

        /* 加入缓存 */
        pageCache.put(pageIndex, bitmap)

        val page = CoursewarePage(pageIndex, bitmap, width, height)
        listener?.onPageReady(page)

        Log.d(TAG, "PDF页面渲染: 第${pageIndex + 1}页, ${width}x${height}")
    }

    /* ==================== 图片加载 ==================== */

    /**
     * 加载单张图片作为课件
     */
    private fun loadSingleImage(filePath: String) {
        val bitmap = BitmapFactory.decodeFile(filePath)
        if (bitmap == null) {
            listener?.onLoadError("图片解码失败: $filePath")
            return
        }

        val file = File(filePath)
        currentCourseware = CoursewareInfo(
            coursewareId = file.nameWithoutExtension,
            title = file.nameWithoutExtension,
            type = CoursewareType.IMAGE,
            localPath = filePath,
            totalPages = 1
        )
        currentPage = 0

        pageCache.put(0, bitmap)
        listener?.onCoursewareLoaded(currentCourseware!!)
        listener?.onPageReady(CoursewarePage(0, bitmap, bitmap.width, bitmap.height))

        Log.i(TAG, "图片课件加载: ${bitmap.width}x${bitmap.height}")
    }

    /**
     * 加载图片集（目录下多张图片作为多页课件）
     */
    private fun loadImageSet(dirPath: String) {
        val dir = File(dirPath)
        val imageFiles = dir.listFiles { file ->
            file.extension.lowercase() in listOf("png", "jpg", "jpeg", "bmp")
        }?.sortedBy { it.name } ?: emptyList()

        if (imageFiles.isEmpty()) {
            listener?.onLoadError("图片集为空: $dirPath")
            return
        }

        imagePages.clear()
        imageFiles.forEach { imagePages.add(it.absolutePath) }

        currentCourseware = CoursewareInfo(
            coursewareId = dir.name,
            title = dir.name,
            type = CoursewareType.IMAGE_SET,
            localPath = dirPath,
            totalPages = imageFiles.size
        )
        currentPage = 0

        listener?.onCoursewareLoaded(currentCourseware!!)

        /* 加载第一页 */
        loadImagePage(0)

        Log.i(TAG, "图片集加载: ${imageFiles.size}页")
    }

    /**
     * 加载图片集的指定页
     */
    private fun loadImagePage(pageIndex: Int) {
        if (pageIndex < 0 || pageIndex >= imagePages.size) return

        pageCache.get(pageIndex)?.let { cached ->
            listener?.onPageReady(CoursewarePage(pageIndex, cached, cached.width, cached.height))
            return
        }

        val bitmap = BitmapFactory.decodeFile(imagePages[pageIndex])
        if (bitmap != null) {
            pageCache.put(pageIndex, bitmap)
            listener?.onPageReady(CoursewarePage(pageIndex, bitmap, bitmap.width, bitmap.height))
        }
    }

    /**
     * PPT加载（转换为图片后渲染）
     * 实际使用Apache POI或云端转换服务
     */
    private fun loadPptAsImages(filePath: String) {
        Log.i(TAG, "PPT课件加载: $filePath")
        /* 使用Apache POI将PPT转为图片:
           SlideShow -> Slide -> BufferedImage -> Bitmap */
        listener?.onLoadError("PPT格式需要转换服务支持")
    }

    /* ==================== 翻页控制 ==================== */

    /**
     * 翻到下一页
     */
    fun nextPage(): Boolean {
        val total = currentCourseware?.totalPages ?: return false
        if (currentPage >= total - 1) return false

        currentPage++
        loadPage(currentPage)
        Log.d(TAG, "翻到第${currentPage + 1}/${total}页")
        return true
    }

    /**
     * 翻到上一页
     */
    fun previousPage(): Boolean {
        if (currentPage <= 0) return false

        currentPage--
        loadPage(currentPage)
        Log.d(TAG, "翻到第${currentPage + 1}/${currentCourseware?.totalPages}页")
        return true
    }

    /**
     * 跳转到指定页
     */
    fun goToPage(pageIndex: Int): Boolean {
        val total = currentCourseware?.totalPages ?: return false
        if (pageIndex < 0 || pageIndex >= total) return false

        currentPage = pageIndex
        loadPage(pageIndex)
        return true
    }

    /**
     * 加载指定页面（根据课件类型调用不同方法）
     */
    private fun loadPage(pageIndex: Int) {
        executor.submit {
            when (currentCourseware?.type) {
                CoursewareType.PDF -> renderPdfPage(pageIndex)
                CoursewareType.IMAGE_SET -> loadImagePage(pageIndex)
                else -> { /* 单图片无需翻页 */ }
            }
        }

        /* 预加载相邻页面 */
        executor.submit { preloadAdjacentPages(pageIndex) }
    }

    /**
     * 预加载前后页面到缓存
     */
    private fun preloadAdjacentPages(pageIndex: Int) {
        val total = currentCourseware?.totalPages ?: return

        listOf(pageIndex - 1, pageIndex + 1).forEach { adjPage ->
            if (adjPage in 0 until total && pageCache.get(adjPage) == null) {
                when (currentCourseware?.type) {
                    CoursewareType.PDF -> {
                        /* 预渲染PDF页面 */
                        val renderer = pdfRenderer ?: return
                        val pdfPage = renderer.openPage(adjPage)
                        val scale = RENDER_DPI.toFloat() / 72f
                        val w = (pdfPage.width * scale).toInt()
                        val h = (pdfPage.height * scale).toInt()
                        val bmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
                        pdfPage.render(bmp, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
                        pdfPage.close()
                        pageCache.put(adjPage, bmp)
                    }
                    CoursewareType.IMAGE_SET -> {
                        if (adjPage < imagePages.size) {
                            BitmapFactory.decodeFile(imagePages[adjPage])?.let {
                                pageCache.put(adjPage, it)
                            }
                        }
                    }
                    else -> {}
                }
            }
        }
    }

    /* ==================== 资源管理 ==================== */

    /**
     * 关闭PDF渲染器
     */
    private fun closePdfRenderer() {
        pdfRenderer?.close()
        pdfRenderer = null
        pdfFileDescriptor?.close()
        pdfFileDescriptor = null
    }

    /**
     * 释放所有资源
     */
    fun release() {
        closePdfRenderer()
        pageCache.evictAll()
        imagePages.clear()
        executor.shutdown()
        Log.i(TAG, "课件加载器已释放")
    }
}
