import os
from flask import Flask, render_template, request, jsonify, send_from_directory
import joblib # type: ignore
from werkzeug.utils import secure_filename
import cv2
import numpy as np
import math

# Setup Flask
app = Flask(__name__, template_folder='D:/Kuliah/SKRIPSI/Kakao/templates')
app.config['UPLOAD_FOLDER'] = 'D:/Kuliah/SKRIPSI/Kakao/uploads'

# Pastikan folder uploads ada
if not os.path.exists(app.config['UPLOAD_FOLDER']):
    os.makedirs(app.config['UPLOAD_FOLDER'])

@app.route('/uploads/<filename>')
def uploaded_file(filename):
    return send_from_directory(app.config['UPLOAD_FOLDER'], filename)

# Load model KNN
model_path = os.path.join('D:\Kuliah\SKRIPSI\Kakao\model\model_knn.pkl')
with open(model_path, 'rb') as model_file:
    model_knn = joblib.load(model_file)

# Fungsi untuk memvalidasi file gambar
def allowed_file(filename):
    allowed_extensions = {'png', 'jpg', 'jpeg'}
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in allowed_extensions

# Fungsi preprocessing gambar (GLCM)
def preprocess_image(image_path):
    img = cv2.imread(image_path)
    resized_img = cv2.resize(img, (32, 43))
    gray_img = cv2.cvtColor(resized_img, cv2.COLOR_BGR2GRAY)

    def glcm(img, angle):
        max_val = np.max(img)
        imgTmp = np.zeros([max_val+1, max_val+1])
        for i in range(len(img)-1):
            for j in range(len(img[i])-1):
                if angle == 0:
                    imgTmp[img[i][j], img[i,j+1]] += 1
                elif angle == 45:
                    if i > 0 and j < len(img[i])-1:
                        imgTmp[img[i][j], img[i-1,j+1]] += 1
                elif angle == 90:
                    if i > 0:
                        imgTmp[img[i][j], img[i-1,j]] += 1
                elif angle == 135:
                    if i > 0 and j > 0:
                        imgTmp[img[i][j], img[i-1,j-1]] += 1
        transpos = np.transpose(imgTmp)
        data = imgTmp + transpos
        data /= np.sum(data)
        return data

    def contrast(data):
        contrast_val = 0
        for i in range(len(data)):
            for j in range(len(data)):
                contrast_val += data[i,j] * pow(i-j, 2)
        return contrast_val

    def entropy(data):
        entropy_val = 0
        for i in range(len(data)):
            for j in range(len(data)):
                if data[i,j] > 0:
                    entropy_val += - (data[i,j] * math.log(data[i,j]))
        return entropy_val

    def homogenitas(data):
        homogenitas_val = 0
        for i in range(len(data)):
            for j in range(len(data)):
                homogenitas_val += data[i,j] * (1 + (pow(i-j, 2)))
        return homogenitas_val

    def energy(data):
        energy_val = 0
        for i in range(len(data)):
            for j in range(len(data)):
                energy_val += data[i,j] ** 2
        return energy_val

    angles = [0, 45, 90, 135]
    features = []
    for angle in angles:
        glcm_matrix = glcm(gray_img, angle)
        features.append(energy(glcm_matrix))
        features.append(homogenitas(glcm_matrix))
        features.append(entropy(glcm_matrix))
        features.append(contrast(glcm_matrix))

    return np.array(features).reshape(1, -1)  # Mengembalikan 16 fitur

@app.route('/')
def index():
    return render_template('dashboard.html')

@app.route('/panduan')
def panduan():
    return render_template('panduan.html')

@app.route('/identifikasi', methods=['GET', 'POST'])
def identifikasi():
    if request.method == 'POST':
        if 'file' not in request.files:
            return jsonify({"error": "No file part"})
        
        file = request.files['file']
        
        if file.filename == '':
            return jsonify({"error": "No selected file"})
        
        if file and allowed_file(file.filename):
            filename = secure_filename(file.filename)
            filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
            
            # Simpan file gambar
            file.save(filepath)
            
            try:
                # Preprocess gambar untuk prediksi
                image_features = preprocess_image(filepath)
                
                # Prediksi dengan model KNN
                prediction = model_knn.predict(image_features)
                predicted_label = prediction[0]
                
                # Menghitung probabilitas (akurasi) prediksi
                probabilities = model_knn.predict_proba(image_features)
                accuracy = np.max(probabilities)
                
                # Peta label ke deskripsi
                label_descriptions = {
                    'Healthy': "Ini adalah gambar buah kakao yang sehat.",
                    'Monilia': "Monilia disebabkan oleh jamur Moniliophthora roreri. solusi pertama dilakukan untuk Monilia secara penanganan sama dengan Phytophthora, namun jika ditemukan di Indonesia perlu adanya tindakan awal berupa eradikasi agar penyebab penyakit itu hilang sama sekali",
                    'Phytophthora': "Phytophthora disebabkan oleh jamur Phytophthora palmivora. Untuk penyakit Phytophtora: Solusi pertama dilakukan sanitasi buah yang terserang busuk buah walaupun terserang masih kecil dan di buang jauh dari tanaman kakao dengan cara memendam dengan timbunan lebih dari 30 cm. Kemudian dilakukan penyemprotan dengan fungisida terdaftar di Indonesia waktu itu atau bisa menggunakan bahan aktif Azoxystrobin sesuai dosis di label",
                }
                description = label_descriptions.get(predicted_label, "Tidak diketahui")
                
                # Return hasil sebagai response JSON
                return jsonify({
                    "filename": filename,
                    "predicted_label": predicted_label,
                    "description": description,
                    "accuracy": f"{accuracy * 100:.2f}%"  # Akurasi dalam persen
                })
            except Exception as e:
                return jsonify({"error": str(e)})
        else:
            return jsonify({"error": "File type not allowed. Please upload PNG, JPG, or JPEG images."})
    
    return render_template('identifikasi.html')

if __name__ == '__main__':
    app.run(debug=True)
