package com.assimilate.alltrans.common

import android.content.Context
import android.util.Log
import com.assimilate.alltrans.MyApp
import com.assimilate.alltrans.curview.GraphicOverlay
import com.assimilate.alltrans.model.LanguagesConstants
import com.assimilate.alltrans.model.PreferenceLanguageUtils
import com.google.android.gms.tasks.Task
import com.google.mlkit.vision.common.InputImage
import com.google.mlkit.vision.text.Text
import com.google.mlkit.vision.text.TextRecognition
import com.google.mlkit.vision.text.TextRecognizer
import com.google.mlkit.vision.text.TextRecognizerOptionsInterface

/** Processor for the text detector demo. */
class TextRecognitionProcessor(
    private val context: Context,
    textRecognizerOptions: TextRecognizerOptionsInterface,
    private val callback: TextRecognitionCallback? = null
    ) : VisionProcessorBase<Text>(context) {

    interface TextRecognitionCallback {
        fun onTextRecognized(text: Text,graphicOverlay: GraphicOverlay)
        fun onTextFailure(e: Exception)
    }

    private val textRecognizer: TextRecognizer = TextRecognition.getClient(textRecognizerOptions)

    override fun stop() {
        super.stop()
        textRecognizer.close()
    }

    override fun detectInImage(image: InputImage): Task<Text> {
        return textRecognizer.process(image)
    }

    override fun onSuccess(text: Text, graphicOverlay: GraphicOverlay) {
        PreferenceLanguageUtils.putString("language_source", getMostFrequentLanguage(text))
        logExtrasForTesting(text)
        // 调用回调
        callback?.onTextRecognized(text,graphicOverlay)
    }

    override fun onFailure(e: Exception) {
        Log.w(TAG, "Text detection failed.$e")
        callback?.onTextFailure(e)
    }

    // 推测最可能的语言
    private fun getMostFrequentLanguage(text: Text): String {
        val languageCount = mutableMapOf<String, Int>()
        for (textBlock in text.textBlocks) {
            for (line in textBlock.lines) {
                for (element in line.elements) {
                    val language = element.recognizedLanguage
                    if (language != "und-Latn") {
                        if (languageCount.containsKey(language)) {
                            languageCount[language] = languageCount[language]!! + 1
                        } else {
                            languageCount[language] = 1
                        }
                    }
                }
            }
        }

        val maxCode = languageCount.maxByOrNull { it.value }?.key ?: "zh_CN"

        val lanByCode = LanguagesConstants.getInstance()
            .getLanguageByLanguageCode(maxCode, MyApp.applicationContext())


        return if (lanByCode != null) {
            lanByCode.language
        } else {
            "English"
        }
    }

    companion object {
        private const val TAG = "TextRecProcessor"
        private fun logExtrasForTesting(text: Text?) {
            if (text != null) {
                Log.v(MANUAL_TESTING_LOG, "text context is : " + text.text)
                Log.v(MANUAL_TESTING_LOG, "Detected text has : " + text.textBlocks.size + " blocks")
                for (i in text.textBlocks.indices) {
                    val lines = text.textBlocks[i].lines
                    Log.v(
                        MANUAL_TESTING_LOG,
                        String.format("Detected text block %d has %d lines", i, lines.size)
                    )
                    for (j in lines.indices) {
                        val elements = lines[j].elements

                        Log.v(
                            MANUAL_TESTING_LOG,
                            String.format("Detected text line %d has %d elements", j, elements.size)
                        )
                        for (k in elements.indices) {
                            val element = elements[k]
                            Log.v("推测是什么语言", element.recognizedLanguage)

                            Log.v(
                                MANUAL_TESTING_LOG,
                                String.format("Detected text element %d says: %s", k, element.text)
                            )
                            Log.v(
                                MANUAL_TESTING_LOG,
                                String.format(
                                    "Detected text element %d has a bounding box: %s",
                                    k,
                                    element.boundingBox!!.flattenToString()
                                )
                            )
                            Log.v(
                                MANUAL_TESTING_LOG,
                                String.format(
                                    "Expected corner point size is 4, get %d",
                                    element.cornerPoints!!.size
                                )
                            )
                            for (point in element.cornerPoints!!) {
                                Log.v(
                                    MANUAL_TESTING_LOG,
                                    String.format(
                                        "Corner point for element %d is located at: x - %d, y = %d",
                                        k,
                                        point.x,
                                        point.y
                                    )
                                )
                            }
                        }
                    }
                }
            }
        }
    }
}
