package com.assimilate.alltrans.common

import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.RectF
import android.graphics.Typeface
import android.text.Layout
import android.text.StaticLayout
import android.text.TextPaint
import android.util.Log
import com.assimilate.alltrans.MyApp
import com.assimilate.alltrans.curview.GraphicOverlay
import com.google.mlkit.vision.text.Text
import kotlin.math.max
import kotlin.math.min

class TextGraphic(
    overlay: GraphicOverlay?,
    private val text: Text,
    private val textShow: Boolean,
    private val needTrans: Boolean,
    private val fbFrom: String
) : GraphicOverlay.Graphic(overlay) {

    private val shouldGroupRecognizedTextInBlocks: Boolean =
        PreferenceUtils.shouldGroupRecognizedTextInBlocks(MyApp.applicationContext())
    private val showLanguageTag: Boolean =
        PreferenceUtils.showLanguageTag(MyApp.applicationContext())
    private val showConfidence: Boolean =
        PreferenceUtils.shouldShowTextConfidence(MyApp.applicationContext())


    private val textPaint: TextPaint = TextPaint().apply {
        color = TEXT_COLOR
        textSize = TEXT_SIZE
        typeface = Typeface.create(Typeface.DEFAULT, Typeface.BOLD)
        isFakeBoldText = true
    }
    private val labelPaint: Paint = Paint().apply {
        color = MARKER_COLOR
        style = Paint.Style.FILL
    }
    private var hiddenTextBlocks: MutableList<Boolean> =
        MutableList(text.textBlocks.size) { !textShow }
    private var isVisible: Boolean

    private var isLoading: Boolean = false

    // 翻译后的文本
    private var translatedTextBlocks: List<String> = listOf()


    init {
        isVisible = textShow

        if (needTrans) {
            isLoading = true
            TranslationManager(text, fbFrom) { translatedTextPairs ->
                translatedTextBlocks = translatedTextPairs.map { it.first }
                isLoading = false
                // 可以同时打印原Text和翻译后的结果
                translatedTextPairs.forEach { (translated, original) ->
                    Log.d("Translation", "Original: $original -> Translated: $translated")
                }

                postInvalidate()
            }
        }
        // Redraw the overlay, as this graphic has been added.
        postInvalidate()
    }


    override fun draw(canvas: Canvas) {
        if (!isVisible) return

        for ((index, textBlock) in text.textBlocks.withIndex()) {
            if (hiddenTextBlocks[index]) continue
            drawTextBlock(textBlock, canvas, index)
        }
    }

    private fun drawLoadingIndicator(textBlock: Text.TextBlock, canvas: Canvas) {
        val rect = RectF(textBlock.boundingBox)
        val centerX = (rect.left + rect.right) / 2
        val centerY = (rect.top + rect.bottom) / 2
        val radius = min(rect.width(), rect.height()) / 4

        val paint = Paint().apply {
            color = Color.BLUE
            style = Paint.Style.STROKE
            strokeWidth = 8f
        }

        canvas.drawCircle(centerX, centerY, radius, paint)
    }


    private fun drawTextBlock(textBlock: Text.TextBlock, canvas: Canvas, index: Int) {
        val translatedBlockText = translatedTextBlocks.getOrNull(index) ?: textBlock.text

        if (shouldGroupRecognizedTextInBlocks) {
            val rect = RectF(textBlock.boundingBox)
            drawText(
                getFormattedText(translatedBlockText, textBlock.recognizedLanguage, null),
                rect,
                canvas,
                textPaint
            )
        }
//        if (isLoading) {
//            drawLoadingIndicator(textBlock, canvas)
//        }
    }

    override fun contains(x: Float, y: Float): Boolean {
        for (textBlock in text.textBlocks) {
            val rect = RectF(textBlock.boundingBox)
            val x0 = translateX(rect.left)
            val x1 = translateX(rect.right)
            rect.left = min(x0, x1)
            rect.right = max(x0, x1)
            rect.top = translateY(rect.top)
            rect.bottom = translateY(rect.bottom)
            if (rect.contains(x, y)) {
                return true
            }
        }
        return false
    }

    fun showTextBlockAt(x: Float, y: Float) {
        isVisible = true
        for ((index, textBlock) in text.textBlocks.withIndex()) {
            val rect = RectF(textBlock.boundingBox)
            val x0 = translateX(rect.left)
            val x1 = translateX(rect.right)
            rect.left = min(x0, x1)
            rect.right = max(x0, x1)
            rect.top = translateY(rect.top)
            rect.bottom = translateY(rect.bottom)
            if (rect.contains(x, y)) {
                hiddenTextBlocks[index] = false
                postInvalidate()
                break
            }
        }
    }

    fun hideTextBlock() {
        isVisible = false
        for (i in hiddenTextBlocks.indices) {
            hiddenTextBlocks[i] = true
        }
        postInvalidate()
    }

    private fun getFormattedText(text: String, languageTag: String, confidence: Float?): String {
        val res = if (showLanguageTag) String.format(
            TEXT_WITH_LANGUAGE_TAG_FORMAT,
            languageTag,
            text
        ) else text
        return if (showConfidence && confidence != null) String.format(
            "%s (%.2f)",
            res,
            confidence
        ) else res
    }

    private fun drawText(text: String, rect: RectF, canvas: Canvas, paint: TextPaint) {
        val x0 = translateX(rect.left)
        val x1 = translateX(rect.right)
        rect.left = min(x0, x1)
        rect.right = max(x0, x1)
        rect.top = translateY(rect.top)
        rect.bottom = translateY(rect.bottom)

        // 绘制背景矩形
        canvas.drawRect(rect, labelPaint)

        // 准备文本绘制
        val textPaintCopy = TextPaint(paint)
        val availableWidth = rect.width().toInt()
        val availableHeight = rect.height().toInt()
        var textSize = textPaintCopy.textSize

        var textLayout: StaticLayout
        while (textSize > 0) {
            textPaintCopy.textSize = textSize
            textLayout =
                StaticLayout.Builder.obtain(text, 0, text.length, textPaintCopy, availableWidth)
                    .setAlignment(Layout.Alignment.ALIGN_NORMAL)
                    .setLineSpacing(0.0f, 1.0f)
                    .setIncludePad(false)
                    .build()

            if (textLayout.height <= availableHeight) {
                break
            }
            textSize -= 1
        }

        textLayout =
            StaticLayout.Builder.obtain(text, 0, text.length, textPaintCopy, availableWidth)
                .setAlignment(Layout.Alignment.ALIGN_NORMAL)
                .setLineSpacing(0.0f, 1.0f)
                .setIncludePad(false)
                .build()

        canvas.save()
        canvas.translate(rect.left, rect.top)
        textLayout.draw(canvas)
        canvas.restore()
    }

    companion object {
        private const val TAG = "TextGraphic"
        private const val TEXT_WITH_LANGUAGE_TAG_FORMAT = "%s:%s"
        private val TEXT_COLOR = Color.parseColor("#FF474747")
        private val MARKER_COLOR = Color.parseColor("#FFD9D9D9")
        private const val TEXT_SIZE = 44.0f
    }
}
