// Import library yang dibutuhkan untuk context, bitmap, logging, dan TensorFlow Lite
import android.content.Context
import android.graphics.Bitmap
import android.util.Log
import com.example.palmguardapp.ml.Model
import org.tensorflow.lite.DataType
import org.tensorflow.lite.support.common.ops.NormalizeOp
import org.tensorflow.lite.support.image.ImageProcessor
import org.tensorflow.lite.support.image.TensorImage
import org.tensorflow.lite.support.image.ops.ResizeOp
import org.tensorflow.lite.support.tensorbuffer.TensorBuffer

// Kelas utama untuk klasifikasi gambar menggunakan model ML TFLite
class ImageClassifier(private val context: Context) {

    // Ukuran input gambar yang dibutuhkan model
    private val imageSize = 224

    // Daftar label kelas dari model
    private val classes = arrayOf("Brown Spots", "Healthy", "Unknown")

    // ImageProcessor untuk mengubah ukuran dan menormalisasi gambar agar sesuai dengan input model
    private val imageProcessor = ImageProcessor.Builder()
        .add(ResizeOp(imageSize, imageSize, ResizeOp.ResizeMethod.BILINEAR)) // Resize gambar ke 224x224
        .add(NormalizeOp(0f, 255f)) // Normalisasi piksel gambar ke range 0–1
        .build()

    // Fungsi utama untuk mengklasifikasikan gambar
    fun classifyImage(image: Bitmap): Pair<String, Float>? {
        // Membuat instance model
        val model = Model.newInstance(context)

        // Mengonversi gambar bitmap ke TensorImage dengan tipe data FLOAT32
        val tensorImage = TensorImage(DataType.FLOAT32)
        val convertedBitmap = image.copy(Bitmap.Config.ARGB_8888, true) // Salin bitmap agar bisa diolah
        tensorImage.load(convertedBitmap)

        // Proses preprocessing gambar: resize + normalisasi
        val processedImage = imageProcessor.process(tensorImage)

        // Menyiapkan buffer input model dengan shape dan tipe data yang sesuai
        val inputFeature0 = TensorBuffer.createFixedSize(intArrayOf(1, imageSize, imageSize, 3), DataType.FLOAT32)
        inputFeature0.loadBuffer(processedImage.buffer)

        // Memproses input melalui model dan mendapatkan output
        val outputs = model.process(inputFeature0)
        val outputFeature0 = outputs.outputFeature0AsTensorBuffer

        // Mengambil array probabilitas prediksi dari hasil output
        val confidences = outputFeature0.floatArray
        Log.d("ImageClassifier", "Confidence: ${confidences.size}")

        // Logging setiap confidence untuk tiap kelas
        for (i in confidences.indices) {
            Log.d("ImageClassifier", "Class $i (${classes[i]}): ${confidences[i]}")
        }

        // Mencari indeks prediksi dengan confidence tertinggi
        val maxPos = confidences.indices.maxByOrNull { confidences[it] } ?: -1
        val maxConfidence = (maxOf(confidences[maxPos]) * 100).toFloat() // Konversi ke persen
        Log.d("ImageClassifier", "Max Position: $maxPos, Max Confidence: $maxConfidence")

        // Menutup instance model untuk membebaskan resource
        model.close()

        // Mengembalikan hasil klasifikasi jika confidence mencukupi dan bukan kelas Unknown
        return if (maxPos >= 0 && maxConfidence > THRESHOLD_CONFIDENCE && classes[maxPos] != "Unknown") {
            Pair(classes[maxPos], maxConfidence)
        } else {
            null // Tidak ada hasil yang cukup meyakinkan
        }
    }

    companion object {
        // Batas minimum confidence yang dianggap valid (dalam persen)
        private const val THRESHOLD_CONFIDENCE = 0.5f
    }
}
