from flask import jsonify
from PIL import Image
from io import BytesIO
import face_recognition
import cv2
from ultralytics import YOLO
import os
import uuid
from werkzeug.utils import secure_filename
from translations import trans

ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'webp','gif'}

def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
           
def response_formatter(messages, status, result = False):
    response = {
        'messages': messages,
        'status': status,
        'result': result
    }
    return jsonify(response)

def rotate_image(image):
    image = Image.open(image)
    rotated_image = image.rotate(90, expand=True)
    buffered = BytesIO()
    rotated_image.save(buffered, format="JPEG")
    return face_recognition.load_image_file(buffered)

def calculate_brightness(image):
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    print(gray.mean())
    return gray.mean()

def face_eval(loaded_image, face_locations, min_wide_face_area = 20000, laplacian_thresold = 500, lang = 'en'):
    top, right, bottom, left = face_locations[0]
    width = right - left
    height = bottom - top
    center_x = left + (width // 2)
    center_y = top + (height // 2)
    image_width, image_height = loaded_image.shape[1], loaded_image.shape[0]

    grayscale_image = cv2.cvtColor(loaded_image, cv2.COLOR_BGR2GRAY)
    face_area = grayscale_image[top:bottom, left:right]
    laplacian = cv2.Laplacian(face_area, cv2.CV_64F).var()
    # print(f'laplacian = {laplacian}')
    if laplacian < laplacian_thresold:
        return {'message': trans[lang]['failed_blur'], 'status': 'failed', 'result': False}

    if width * height < min_wide_face_area:
         return {'message': trans[lang]['failed_area'], 'status': 'failed', 'result': False}
    
    if center_x >= image_width * 0.4 and center_x <= image_width * 0.6 and \
            center_y >= image_height * 0.4 and center_y <= image_height * 0.6:
        return {'message': trans[lang]['registration_successful'], 'status':'success', 'result': True }
    else:
        return {'message': trans[lang]['face_position'], 'status':'failed', 'result': False }
    
def face_eval_regis(loaded_image, face_locations, min_wide_face_area = 20000, laplacian_thresold = 500, lang = 'en'):
    top, right, bottom, left = face_locations[0]
    width = right - left
    height = bottom - top
    center_x = left + (width // 2)
    center_y = top + (height // 1.5)
    image_width, image_height = loaded_image.shape[1], loaded_image.shape[0]

    grayscale_image = cv2.cvtColor(loaded_image, cv2.COLOR_BGR2GRAY)
    face_area = grayscale_image[top:bottom, left:right]
    laplacian = cv2.Laplacian(face_area, cv2.CV_64F).var()
    # print(f'laplacian = {laplacian}')
    if laplacian < laplacian_thresold:
        return {'message': trans[lang]['failed_blur'], 'status': 'failed', 'result': False}

    if width * height < min_wide_face_area:
         return {'message': trans[lang]['failed_area'], 'status': 'failed', 'result': False}
    
    if center_x >= image_width * 0.4 and center_x <= image_width * 0.6 and \
            center_y >= image_height * 0.4 and center_y <= image_height * 0.6:
        return {'message': trans[lang]['registration_successful'], 'status':'success', 'result': True }
    else:
        return  {'message': trans[lang]['face_position'], 'status': 'failed', 'result': False}
    
def detect(folder_path, resource):
    # tes yolo
    result = False
    unique_filename = str(uuid.uuid4()) + '_' + secure_filename(resource.filename)
    path = os.path.join(folder_path, unique_filename)
    resource.save(path)
    
    # deteksi object hp
    model = YOLO("custom.pt")
    detects = model.predict(path, verbose=False) # verbose=False ----> untuk hide output di terminal
    detect = detects[0]
    for box in detect.boxes:
        # class_id = detect.names[box.cls[0].item()]
        # cords = box.xyxy[0].tolist()
        # cords = [round(x) for x in cords]
        conf = round(box.conf[0].item(), 2)
        # print("Object type:", class_id)
        # print("Coordinates:", cords)
        # print("Probability:", conf)
        # print("---")
        # print(f'skor = {conf}')
        if(conf > 0.5):
            result = True
            break
    os.remove(path)    
    return result