/*
 * Copyright 2023 Shubham Panchal
 * Licensed under the Apache License, Version 2.0 (the "License");
 * You may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.example.absenkuv3.facex

import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.util.Log
import android.view.SurfaceHolder
import android.view.SurfaceView
import androidx.camera.core.CameraSelector
import androidx.core.graphics.toRectF
import com.example.absenkuv3.broadcast.BroadcastSender

// Defines an overlay on which the boxes and text will be drawn.
class BoundingBoxOverlay( context: Context , attributeSet: AttributeSet )
    : SurfaceView( context , attributeSet ) , SurfaceHolder.Callback {
    var boundValue = false
    var cocok = false
    // Variables used to compute output2overlay transformation matrix
    // These are assigned in FrameAnalyser.kt
    var areDimsInit = false
    var frameHeight = 0
    var frameWidth = 0

    var cameraFacing : Int = CameraSelector.LENS_FACING_FRONT

    // This var is assigned in FrameAnalyser.kt
    var faceBoundingBoxes: ArrayList<Prediction>? = null

    // Determines whether or not "mask" or "no mask" should be displayed.
    var drawMaskLabel = true

    private var output2OverlayTransform: Matrix = Matrix()

    // Paint for boxes and text
    val boxPaint = Paint().apply {
        color = Color.parseColor("#33FF42")
        style = Paint.Style.STROKE
        strokeWidth = 3f
        setShadowLayer(5f, 0f, 0f, Color.BLACK)
    }

    private val textPaint = Paint().apply {
        strokeWidth = 2.0f
        textSize = 32f
        color = Color.WHITE
    }


    override fun surfaceCreated(holder: SurfaceHolder) {
        TODO("Not yet implemented")
    }


    override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
        TODO("Not yet implemented")
    }


    override fun surfaceDestroyed(holder: SurfaceHolder) {
        TODO("Not yet implemented")
    }


    override fun onDraw(canvas: Canvas) {
        if (faceBoundingBoxes.toString() == "[]"){
            // Log.d("facebound", "masuk if")
            boundValue = false
        } else{
            boundValue = true
        }

        // Log.d("facebound", faceBoundingBoxes.toString())

        BroadcastSender.sendCocokBroadcastBound(context, boundValue)
        // super.onDraw(canvas)
        if (faceBoundingBoxes != null) {
            if (!areDimsInit) {
                val viewWidth = canvas!!.width.toFloat()
                val viewHeight = canvas.height.toFloat()
                val xFactor: Float = viewWidth / frameWidth.toFloat()
                val yFactor: Float = viewHeight / frameHeight.toFloat()
                // Scale and mirror the coordinates ( required for front lens )
                output2OverlayTransform.preScale(xFactor, yFactor)
                if( cameraFacing == CameraSelector.LENS_FACING_FRONT ) {
                    output2OverlayTransform.postScale(-1f, 1f, viewWidth / 2f, viewHeight / 2f)
                    // Log.d("MATRIXX2", output2OverlayTransform.toString() )
                }
                areDimsInit = true
            }
            else {
                for (face in faceBoundingBoxes!!) {
                    val boundingBox = face.bbox.toRectF()
                    output2OverlayTransform.mapRect(boundingBox)
                    val lineLength = 100f // Panjang garis tambahan di sudut-sudut

                    val topLeft = PointF(boundingBox.left, boundingBox.top)
                    val topRight = PointF(boundingBox.right, boundingBox.top)
                    val bottomRight = PointF(boundingBox.right, boundingBox.bottom)
                    val bottomLeft = PointF(boundingBox.left, boundingBox.bottom)



                    val path = Path().apply {
                        // Garis sudut kiri atas
                        moveTo(topLeft.x, topLeft.y)
                        lineTo(topLeft.x, topLeft.y + lineLength)
                        moveTo(topLeft.x, topLeft.y)
                        lineTo(topLeft.x + lineLength, topLeft.y)

                        // Garis sudut kanan atas
                        moveTo(topRight.x, topRight.y)
                        lineTo(topRight.x, topRight.y + lineLength)
                        moveTo(topRight.x, topRight.y)
                        lineTo(topRight.x - lineLength, topRight.y)

                        // Garis sudut kanan bawah
                        moveTo(bottomRight.x, bottomRight.y)
                        lineTo(bottomRight.x, bottomRight.y - lineLength)
                        moveTo(bottomRight.x, bottomRight.y)
                        lineTo(bottomRight.x - lineLength, bottomRight.y)

                        // Garis sudut kiri bawah
                        moveTo(bottomLeft.x, bottomLeft.y)
                        lineTo(bottomLeft.x, bottomLeft.y - lineLength)
                        moveTo(bottomLeft.x, bottomLeft.y)
                        lineTo(bottomLeft.x + lineLength, bottomLeft.y)
                    }

                    if (face.label != "Unknown") {
                        boxPaint.color = Color.parseColor("#33FF42")
                        cocok = true
                    } else {
//                        boxPaint.color = Color.parseColor("#FF0000")
                        boxPaint.color = Color.parseColor("#FFFFFF")
                        cocok = false
                    }
                    BroadcastSender.sendCocokBroadcastCocok(context, cocok)
                    canvas?.drawPath(path, boxPaint)
                    // Log.d("MATRIXX2", output2OverlayTransform.toString() )
                    if ( drawMaskLabel ) {
                        canvas?.drawText(
                            face.maskLabel,
                            boundingBox.centerX(),
                            boundingBox.centerY() + 32,
                            textPaint
                        )
                    }
                }
            }
        }
        super.onDraw(canvas)
    }
}
