import tkinter as tk
from tkinter import ttk, messagebox
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from CoolProp.CoolProp import PropsSI
import numpy as np
from PIL import Image, ImageTk
from plyer import notification  # bibliothèque pour les notifications à l'écran
import pandas as pd # biblothèque pour l'exportation des données sur fichier excel
from datetime import datetime
from reportlab.pdfgen.canvas import Canvas
from reportlab.lib.pagesizes import A4, landscape
from PIL import ImageGrab, Image
import win32gui
import os
import xlsxwriter
import openpyxl
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
from openpyxl.utils import get_column_letter
import pandas as pd
import openpyxl
from datetime import datetime


#import pywin32


BASE_DIR = os.path.dirname(os.path.abspath(__file__))
image_path = os.path.join(BASE_DIR, "images", "image 7 points v1 R290.png")

if not os.path.exists(image_path):
    raise FileNotFoundError(f"Image introuvable à l’emplacement : {image_path}")

img = Image.open(image_path)


def sauvegarder_pdf():
    """Sauvegarde la fenêtre principale en PDF avec tous ses éléments."""
    global points_info, root, fig, canvas_widget

    # Vérifier si les données existent
    if not points_info or len(points_info) != 7:
        notification.notify(
            title='Erreur de sauvegarde PDF',
            message='Saisissez d\'abord les données mesurées',
            app_icon=None,
            timeout=5
        )
        return

    try:
        # Générer un nom de fichier avec la date et l'heure
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        filename = f'rapport_R290_{timestamp}.pdf'

        # Sauvegarder d'abord le graphique matplotlib
        fig.savefig('temp_graph.png', bbox_inches='tight', dpi=300)

        # Forcer la mise à jour de l'interface
        root.update()
        root.after(500)  # Attendre que l'interface se mette à jour

        # Mettre la fenêtre au premier plan
        root.lift()
        root.update()
        root.after(500)  # Attendre encore un peu

        # Obtenir les dimensions de la fenêtre
        hwnd = win32gui.GetForegroundWindow()
        rect = win32gui.GetWindowRect(hwnd)
        x = rect[0]
        y = rect[1]
        width = rect[2] - x
        height = rect[3] - y

        # Capturer la fenêtre
        screenshot = ImageGrab.grab(bbox=(x, y, x+width, y+height))

        # Sauvegarder temporairement la capture
        temp_image = "temp_screenshot.png"
        screenshot.save(temp_image)

        # Créer le PDF avec le bon import
        pdf_canvas = Canvas(filename, pagesize=landscape(A4))

        # Calculer les dimensions pour adapter l'image à la page A4 en paysage
        page_width, page_height = landscape(A4)
        aspect_ratio = width / height

        if width > height:
            new_width = page_width - 40
            new_height = new_width / aspect_ratio
        else:
            new_height = page_height - 40
            new_width = new_height * aspect_ratio

        # Centrer l'image sur la page
        x_centered = (page_width - new_width) / 2
        y_centered = (page_height - new_height) / 2

        # Dessiner l'image sur le PDF
        pdf_canvas.drawImage(temp_image, x_centered, y_centered, width=new_width, height=new_height)

        # Finaliser le PDF
        pdf_canvas.save()

        # Supprimer les fichiers temporaires
        os.remove(temp_image)
        os.remove('temp_graph.png')

        # Afficher une notification de succès
        # Message de succès
        messagebox.showinfo(
                "Exportation réussie dans le répertoire de travail ✅",
                f"✅Les données ont été exportées dans le fichier :\n{filename}"
            )

    except Exception as e:
        # En cas d'erreur, afficher une notification
        messagebox.showerror(
            "Erreur d'exportation ! ❌",
            f"Erreur lors de l'exportation :\n\n{str(e)}"
        )
        print(f"Erreur détaillée : {e}")
        import traceback
        traceback.print_exc()

        # Nettoyer les fichiers temporaires en cas d'erreur
        if os.path.exists('temp_screenshot.png'):
            os.remove('temp_screenshot.png')
        if os.path.exists('temp_graph.png'):
            os.remove('temp_graph.png')



def exporter_excel():
    """Exporte les données du tableau de synthèse vers un fichier Excel."""
    global points_info

    # Vérifier si les données existent
    if not points_info or len(points_info) < 7:
        notification.notify(
            title="Erreur d'exportation",
            message="Saisissez d'abord les données mesurées",
            timeout=5
        )
        return

    try:
        # Générer un nom de fichier
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        filename = f'donnees_R290_{timestamp}.xlsx'

        # Créer un nouveau classeur
        workbook = openpyxl.Workbook()
        worksheet = workbook.active
        worksheet.title = 'Données R134a'

        # Définir les en-têtes
        headers = [
            'Point de mesure',
            'Pression (bar)',
            'Température (°C)',
            'Enthalpie (kJ/kg)',
            'Entropie (kJ/(kg·K))',
            'Volume spécifique (m³/kg)',
            'État'
        ]

        # Écrire les en-têtes avec formatage
        for col_num, header in enumerate(headers, 1):
            cell = worksheet.cell(row=1, column=col_num, value=header)
            cell.font = Font(bold=True, color="FFFFFF")
            cell.fill = PatternFill(start_color="4F81BD", end_color="4F81BD", fill_type="solid")
            cell.alignment = Alignment(horizontal="center", vertical="center")
            cell.border = Border(
                left=Side(style="thin"),
                right=Side(style="thin"),
                top=Side(style="thin"),
                bottom=Side(style="thin")
            )

        # Écrire les données ligne par ligne
        for row_num, point in enumerate(points_info, 2):
            # Couleur alternée pour les lignes
            fill_color = PatternFill(
                start_color="E6F3FF" if row_num % 2 == 0 else "CCE7FF",
                end_color="E6F3FF" if row_num % 2 == 0 else "CCE7FF",
                fill_type="solid"
            )

            for col_num, value in enumerate(point, 1):
                cell = worksheet.cell(row=row_num, column=col_num)

                # Convertir les valeurs numériques
                if col_num >= 2 and col_num <= 6:  # Colonnes numériques
                    try:
                        # Essayer de convertir en float
                        if isinstance(value, str):
                            # Remplacer la virgule par un point si nécessaire
                            numeric_value = float(value.replace(',', '.'))
                        else:
                            numeric_value = float(value)
                        cell.value = numeric_value

                        # Format numérique selon la colonne
                        if col_num == 2:  # Pression
                            cell.number_format = '0.00'
                        elif col_num == 3:  # Température
                            cell.number_format = '0.0'
                        elif col_num == 4:  # Enthalpie
                            cell.number_format = '0.00'
                        elif col_num == 5:  # Entropie
                            cell.number_format = '0.000'
                        elif col_num == 6:  # Volume spécifique
                            cell.number_format = '0.0000'

                    except (ValueError, TypeError):
                        # Si la conversion échoue, garder comme texte
                        cell.value = str(value)
                else:
                    # Pour les colonnes texte
                    cell.value = str(value)

                # Appliquer le style à toutes les cellules
                cell.fill = fill_color
                cell.alignment = Alignment(horizontal="center", vertical="center")
                cell.border = Border(
                    left=Side(style="thin"),
                    right=Side(style="thin"),
                    top=Side(style="thin"),
                    bottom=Side(style="thin")
                )

        # Ajuster la largeur des colonnes
        column_widths = [35, 22, 25, 25, 28, 30, 32]
        for col_num, width in enumerate(column_widths, 1):
            column_letter = openpyxl.utils.get_column_letter(col_num)
            worksheet.column_dimensions[column_letter].width = width

        # Figer la première ligne
        worksheet.freeze_panes = 'A2'

        # Sauvegarder le fichier
        workbook.save(filename)
        workbook.close()
    # En cas de succès
        messagebox.showinfo(
            "Exportation réussie ✅",
            f"✅ Les données ont été exportées avec succès  dans le répertoire de travail !\n\nFichier créé : {filename}\nNombre de lignes : {len(points_info)}"
        )

    except Exception as e:
        # En cas d'erreur
        messagebox.showerror(
            "Erreur d'exportation ❌",
            f"Impossible d'exporter les données :\n\n{str(e)}\n\nVérifiez que :\n• Les données sont correctes\n• Le fichier n'est pas ouvert\n• Vous avez les permissions d'écriture"
        )

        # Logs pour le débogage
        print(f"Erreur détaillée : {e}")
        import traceback
        traceback.print_exc()








def calculer_proprietes(pression, temperature):
    try:
        enthalpie = PropsSI('H', 'T', temperature + 273.15, 'P', pression * 100000, 'R290') / 1000  # Modifié pour R290
        entropie = PropsSI('S', 'T', temperature + 273.15, 'P', pression * 100000, 'R290') / 1000  # Modifié pour R290
        volume_specifique = 1 / PropsSI('D', 'T', temperature + 273.15, 'P', pression * 100000, 'R290')  # Modifié pour R290
        T_sat = PropsSI('T', 'P', pression * 100000, 'Q', 0, 'R290') - 273.15  # Modifié pour R290

        if temperature < T_sat:
            etat = "Liquide sous-refroidi"
        elif temperature > T_sat:
            etat = "Gaz surchauffé"
        else:
            qualite = PropsSI('Q', 'T', temperature + 273.15, 'P', pression * 100000, 'R290')  # Modifié pour R290
            etat = f"Diphasique (x = {qualite:.2%})"

        return enthalpie, entropie, volume_specifique, etat, T_sat
    except ValueError:
        return None, None, None, "Erreur", None

def calculer_surchauffe():
    """Calcule et affiche la surchauffe (Point 1)."""
    global points_info

    if len(points_info) != 7:
        messagebox.showerror("Erreur", "Veuillez tracer le diagramme d'abord.")
        return

    # Surchauffe (point 1 - Entrée Compresseur)
    T7 = points_info[6][2]  # Température du point 1
    p7 = points_info[6][1]  # Pression du point 1

    try:
        enthalpie7, entropie7, volume_specifique7, etat7, T_sat7 = calculer_proprietes(p7, T7)
        if T_sat7 is not None:
            surchauffe = T7 - T_sat7
            messagebox.showinfo("Surchauffe", f"Votre calcul : Surchauffe (Point 7): {surchauffe:.2f} °C \n Température au point 7 (bube)': {T7:.2f} °C \n La température de saturation gazeuse: {T_sat7:.2f} °C")
        else:
            messagebox.showerror("Erreur", "Impossible de calculer la surchauffe (Point 1).\nT_sat7 est None")
    except ValueError:
        messagebox.showerror("Erreur", "Impossible de calculer la surchauffe (Point 6).\nErreur de PropsSI")

def calculer_sousrefroidissement():
    """Calcule et affiche le sous-refroidissement (Point 5)."""
    global points_info

    if len(points_info) != 7:
        messagebox.showerror("Erreur", "Veuillez tracer le diagramme d'abord.")
        return

    # Sous-refroidissement (point 5 - Sortie Condenseur)
    T5 = points_info[4][2]  # Température du point 5
    p5 = points_info[4][1]  # Pression du point 5

    try:
        enthalpie5, entropie5, volume_specifique5, etat5, T_sat5 = calculer_proprietes(p5, T5)
        if T_sat5 is not None:
            sousrefroidissement = T_sat5 - T5
            messagebox.showinfo("Sous-refroidissement", f"Votre calcul : Sous-refroidissement (Point 5): {sousrefroidissement:.2f} °C \n La tempérture entrée au détendeur (point 5) : {T5:.2f} °C \n La tempérarure de condensation : {T_sat5:.2f} °C")
        else:
            messagebox.showerror("Erreur", "Impossible de calculer le sous-refroidissement (Point 5).\nT_sat5 est None")
    except ValueError:
        messagebox.showerror("Erreur", "Impossible de calculer le sous-refroidissement (Point 5).\nErreur de PropsSI")

def tracer_diagramme_enthalpique():
    global points_info
    image_label.grid_remove()
    canvas_widget.grid(row=0, column=2, rowspan=15, padx=10, pady=10, sticky="nsew")

    ax.clear()

    # Tracer les courbes de saturation sans glissement
    p_sat = np.logspace(np.log10(0.5), np.log10(42), 500)  # Ajusté pour R290: plage de pression de 0.5 à 42 bar
    t_bubble, t_dew, h_liq, h_vap = [], [], [], []

    for p in p_sat:
        try:
            t_bulb = PropsSI('T', 'P', p * 100000, 'Q', 0, 'R290') - 273.15  # Modifié pour R290
            t_bubble.append(t_bulb)
            h_liq.append(PropsSI('H', 'P', p * 100000, 'Q', 0, 'R290') / 1000)  # Modifié pour R290

            t_d = PropsSI('T', 'P', p * 100000, 'Q', 1, 'R290') - 273.15  # Modifié pour R290
            t_dew.append(t_d)
            h_vap.append(PropsSI('H', 'P', p * 100000, 'Q', 1, 'R290') / 1000)  # Modifié pour R290
        except ValueError:
            pass

    # Tracer les courbes sans glissement
    ax.plot(h_liq, p_sat[:len(h_liq)], 'b-', label='Saturation liquide (bulle)')
    ax.plot(h_vap, p_sat[:len(h_vap)], 'r-', label='Saturation vapeur (rosée)')

    # Tracé des isothermes sans glissement
    for temp in range(-60, 100, 10):  # Ajusté pour R290: plage de température de -60°C à 100°C
        h_iso, p_iso = [], []
        for p in np.logspace(np.log10(0.5), np.log10(42), 300):  # Ajusté pour R290
            try:
                t_bulb = PropsSI('T', 'P', p * 100000, 'Q', 0, 'R290') - 273.15  # Modifié pour R290
                t_dew = PropsSI('T', 'P', p * 100000, 'Q', 1, 'R290') - 273.15  # Modifié pour R290

                if t_bulb <= temp <= t_dew:
                    qualite = (temp - t_bulb) / (t_dew - t_bulb)
                    h = PropsSI('H', 'P', p * 100000, 'Q', qualite, 'R290') / 1000  # Modifié pour R290
                else:
                    h = PropsSI('H', 'T', temp + 273.15, 'P', p * 100000, 'R290') / 1000  # Modifié pour R290
                h_iso.append(h)
                p_iso.append(p)
            except ValueError:
                pass

        if h_iso and p_iso:
            ax.plot(h_iso, p_iso, 'g--', linewidth=0.5)
            ax.text(h_iso[-1] + 5, p_iso[-1], f'{temp}°C', fontsize=6, color='green', ha='right', va='center')

    # Tracé des isotitres
    for titre in np.arange(0.1, 1.0, 0.1):
        h_iso, p_iso = [], []
        for p in np.logspace(np.log10(0.5), np.log10(42), 300):  # Ajusté pour R290
            try:
                h = PropsSI('H', 'P', p * 100000, 'Q', titre, 'R290') / 1000  # Modifié pour R290
                h_iso.append(h)
                p_iso.append(p)
            except ValueError:
                pass

        if h_iso and p_iso:
            ax.plot(h_iso, p_iso, 'y:', linewidth=0.5)
            mid_index = len(h_iso) // 2
            ax.text(h_iso[mid_index], p_iso[mid_index], f'x={titre:.1f}', fontsize=6, color='orange',
                    ha='center', va='center', bbox=dict(facecolor='white', edgecolor='none', alpha=0.7))

    # Tracé des isochores - Valeurs ajustées pour R290
    isochores = [0.005, 0.008, 0.01, 0.015, 0.02, 0.03, 0.05, 0.075, 0.1, 0.15, 0.2, 0.3,0.35,0.4,0.5,0.6,0.7,1]  # Ajusté pour R290
    for v in isochores:
        h_iso, p_iso = [], []
        for t in np.linspace(-60, 100, 200):  # Ajusté pour R290
            try:
                p = PropsSI('P', 'T', t + 273.15, 'D', 1 / v, 'R290') / 100000  # Modifié pour R290
                h = PropsSI('H', 'T', t + 273.15, 'D', 1 / v, 'R290') / 1000  # Modifié pour R290
                h_iso.append(h)
                p_iso.append(p)
            except ValueError:
                pass

        if h_iso and p_iso:
            ax.plot(h_iso, p_iso, 'm:', linewidth=0.5)
            ax.text(h_iso[-1], p_iso[-1], f'{v:.3f}', fontsize=6, color='magenta', ha='left', va='top', rotation=10)

    # Tracé des isentropes - Valeurs ajustées pour R290
    offset_h = 0  # Ajustez cette valeur selon le décalage souhaité
    for s in np.arange(1.8, 3.3, 0.1):  # Ajusté pour R290: valeurs d'entropie typiques pour le propane
        h_iso, p_iso = [], []
        for t in np.linspace(-60, 100, 200):  # Ajusté pour R290
            try:
                p = PropsSI('P', 'T', t + 273.15, 'S', s * 1000, 'R290') / 100000  # Modifié pour R290
                h = PropsSI('H', 'T', t + 273.15, 'S', s * 1000, 'R290') / 1000 + offset_h  # Modifié pour R290
                h_iso.append(h)
                p_iso.append(p)
            except ValueError:
                pass

        if h_iso and p_iso:
            ax.plot(h_iso, p_iso, 'k:', linewidth=0.5)
            ax.text(h_iso[-1] + offset_h, p_iso[-1], f'{s:.3f}', fontsize=6, color='black', ha='right', va='top',
                   rotation=60)

    # Tracer les points du cycle
    global points_info
    points_info = []

    labels_points = ["Entrée Compresseur", "Sortie Compresseur", "Entrée Condenseur",
                     "Sortie Condenseur", "Entrée Détendeur", "Sortie Détendeur", "Sortie Évaporateur"]
    colors_points = ['cyan', 'magenta', 'green', 'orange', 'black', 'purple', 'brown']

    for i in range(7):
        pression = float(entries_p[i].get())
        temperature = float(entries_t[i].get())

        if i == 5:  # Sortie détendeur
            enthalpie = points_info[4][3]
            entropie = points_info[4][4]
            volume_specifique = 1 / PropsSI('D', 'H', enthalpie * 1000, 'P', pression * 100000, 'R290')  # Modifié pour R290
            try:
                qualite = PropsSI('Q', 'H', enthalpie * 1000, 'P', pression * 100000, 'R290')  # Modifié pour R290
                etat = f"Bi-état (titre = {qualite * 100:.1f}%)"
            except ValueError:
                etat = "Inconnu"
        else:
            enthalpie, entropie, volume_specifique, etat, _ = calculer_proprietes(pression, temperature)

        points_info.append((labels_points[i], pression, temperature, enthalpie, entropie, volume_specifique, etat))

        ax.plot(enthalpie, pression, 'o', color=colors_points[i])
        ax.text(enthalpie, pression, f"{i + 1}", fontsize=8, color=colors_points[i])

    # Tracer les lignes entre les points
    for i in range(len(points_info) - 1):
        ax.plot([points_info[i][3], points_info[i + 1][3]], [points_info[i][1], points_info[i + 1][1]], '-',
                color='gray')

    ax.set_xscale('linear')
    ax.set_yscale('log')
    ax.set_xlim(50, 800)  # Ajusté pour R290: plages d'enthalpie typiques pour le propane
    ax.set_ylim(0.5, 42)  # Ajusté pour R290: plages de pression typiques pour le propane
    ax.set_xlabel('Enthalpie (kJ/kg)')
    ax.set_ylabel('Pression (bar)')
    ax.set_title('Diagramme Enthalpique du R290 (Propane)')  # Modifié pour R290
    ax.legend(loc='upper right', bbox_to_anchor=(1, 1), fontsize='x-small')
    ax.grid(True)

    canvas.draw()

    # Mettre à jour le tableau de synthèse
    info_text = "Point de mesure\t\tPression(bar)\t\tTempratures(°C)\t\tEnthalpie(kJ/kg)\tEntropie(kJ/(kg·K))\tVolume spécifique(m³/kg)\tÉtat\n"
    info_text += "-" * 160 + "\n"

    for point in points_info:
        info_text += f"{point[0]}\t{point[1]:.2f}\t\t\t{point[2]:.2f}\t\t\t{point[3]:.2f}\t\t\t{point[4]:.4f}\t\t\t{point[5]:.6f}\t\t\t{point[6]}\n"

    info_label.config(text=info_text, font=('Courier', 8))



def afficher_image():
    canvas_widget.grid_remove()
    image_label.grid(row=0, column=2, rowspan=15, padx=10, pady=10, sticky="nsew")

def afficher_graphique():

    image_label.grid_remove()
    canvas_widget.grid(row=0, column=2, rowspan=15, padx=10, pady=10, sticky="nsew")

def calculer_cop(h1, h2, h3, h4):
    """Calcule le COP à partir des enthalpies des points 1, 2, 4 et 5."""
    try:
        cop = (h3 - h4) / (h2 - h1)
        return cop
    except ZeroDivisionError:
        return None  # Gérer le cas où h2 = h1

def COP():
    """Calcule et affiche le COP dans une boîte de dialogue."""
    global points_info  # Assure-toi d'accéder à la variable globale
    if len(points_info) != 7:
        messagebox.showerror("Erreur", "Veuillez tracer le diagramme d'abord.")
        return

    # Récupérer les enthalpies depuis points_info
    h1 = points_info[0][3]  # Enthalpie du point 1 - le chiffre [3] correspond à l'enthalpie
    h2 = points_info[1][3]  # Enthalpie du point 2
    h3 = points_info[2][3]  # Enthalpie du point 3
    h4 = points_info[3][3]  # Enthalpie du point 4

    cop = calculer_cop(h1, h2, h3, h4)

    if cop is not None:
        messagebox.showinfo("COP", f"Le COP est : {cop:.2f}")
    else:
        messagebox.showerror("Erreur", "Impossible de calculer le COP (division par zéro ?).")

def calculer_eer(h11, h22, h6, h7):
    """Calcule le EER à partir des enthalpies des points 1, 2, 6 et 7."""
    try:
        eer = (h7 - h6) / (h22 - h11)
        return eer
    except ZeroDivisionError:
        return None  # Gérer le cas où h2 = h1

def EER():
    """Calcule et affiche le EER dans une boîte de dialogue."""
    global points_info  # Assure-toi d'accéder à la variable globale
    if len(points_info) != 7:
        messagebox.showerror("Erreur", "Veuillez tracer le diagramme d'abord.")
        return

    # Récupérer les enthalpies depuis points_info
    h11 = points_info[0][3]  # Enthalpie du point 1 - le chiffre [3] correspond à l'enthalpie
    h22 = points_info[1][3]  # Enthalpie du point 2
    h6 = points_info[5][3]  # Enthalpie du point 6
    h7 = points_info[6][3]  # Enthalpie du point 7

    eer = calculer_eer(h11, h22, h6, h7)

    if eer is not None:
        messagebox.showinfo("EER", f"Le coefficient d'efficacité EER est : {eer:.2f}")
    else:
        messagebox.showerror("Erreur", "Impossible de calculer le EER (division par zéro ?).")



def afficher_graphique_complet():
    global points_info

    p_sat = np.logspace(np.log10(0.5), np.log10(42), 500)
    h_liq, h_vap = [], []
    for p in p_sat:
        try:
            h_liq.append(PropsSI('H', 'P', p * 100000, 'Q', 0, 'R290') / 1000)
            h_vap.append(PropsSI('H', 'P', p * 100000, 'Q', 1, 'R290') / 1000)
        except ValueError:
            pass

    isochores = [0.005, 0.008, 0.01, 0.015, 0.02, 0.03, 0.05, 0.075, 0.1, 0.15, 0.2, 0.3,0.35,0.4,0.5,0.6,0.7,1]

    # --- 1. Diagramme vierge AVEC valeurs sur les courbes iso ---
    fig1, ax1 = plt.subplots(figsize=(12, 9))
    ax1.plot(h_liq, p_sat[:len(h_liq)], 'b-', linewidth=3, label='Saturation liquide (bulle)')
    ax1.plot(h_vap, p_sat[:len(h_vap)], 'r-', linewidth=3, label='Saturation vapeur (rosée)')

    for temp in range(-60, 100, 10):
        h_iso, p_iso = [], []
        for p in np.logspace(np.log10(0.5), np.log10(42), 300):
            try:
                t_bulb = PropsSI('T', 'P', p * 100000, 'Q', 0, 'R290') - 273.15
                t_dew = PropsSI('T', 'P', p * 100000, 'Q', 1, 'R290') - 273.15
                if t_bulb <= temp <= t_dew:
                    qualite = (temp - t_bulb) / (t_dew - t_bulb)
                    h = PropsSI('H', 'P', p * 100000, 'Q', qualite, 'R290') / 1000
                else:
                    h = PropsSI('H', 'T', temp + 273.15, 'P', p * 100000, 'R290') / 1000
                h_iso.append(h)
                p_iso.append(p)
            except ValueError:
                pass
        if h_iso and p_iso:
            ax1.plot(h_iso, p_iso, 'g--', linewidth=0.5)
            ax1.text(h_iso[-1] + 5, p_iso[-1], f'{temp}°C', fontsize=6, color='green', ha='right', va='center')

    for titre in np.arange(0.1, 1.0, 0.1):
        h_iso, p_iso = [], []
        for p in np.logspace(np.log10(0.5), np.log10(42), 300):
            try:
                h = PropsSI('H', 'P', p * 100000, 'Q', titre, 'R290') / 1000
                h_iso.append(h)
                p_iso.append(p)
            except ValueError:
                pass
        if h_iso and p_iso:
            ax1.plot(h_iso, p_iso, 'y:', linewidth=0.5)
            mid_index = len(h_iso) // 2
            ax1.text(h_iso[mid_index], p_iso[mid_index], f'x={titre:.1f}', fontsize=6, color='orange',
                    ha='center', va='center', bbox=dict(facecolor='white', edgecolor='none', alpha=0.7))

    for v in isochores:
        h_iso, p_iso = [], []
        for t in np.linspace(-60, 100, 200):
            try:
                p = PropsSI('P', 'T', t + 273.15, 'D', 1 / v, 'R290') / 100000
                h = PropsSI('H', 'T', t + 273.15, 'D', 1 / v, 'R290') / 1000
                h_iso.append(h)
                p_iso.append(p)
            except ValueError:
                pass
        if h_iso and p_iso:
            ax1.plot(h_iso, p_iso, 'm:', linewidth=0.5)
            ax1.text(h_iso[-1], p_iso[-1], f'{v:.3f}', fontsize=6, color='magenta', ha='left', va='top', rotation=10)

    for s in np.arange(1.8, 3.3, 0.1):
        h_iso, p_iso = [], []
        for t in np.linspace(-60, 100, 200):
            try:
                p = PropsSI('P', 'T', t + 273.15, 'S', s * 1000, 'R290') / 100000
                h = PropsSI('H', 'T', t + 273.15, 'S', s * 1000, 'R290') / 1000
                h_iso.append(h)
                p_iso.append(p)
            except ValueError:
                pass
        if h_iso and p_iso:
            ax1.plot(h_iso, p_iso, 'k:', linewidth=0.5)
            ax1.text(h_iso[-1], p_iso[-1], f'{s:.3f}', fontsize=6, color='black', ha='right', va='top', rotation=60)

    ax1.set_xscale('linear')
    ax1.set_yscale('log')
    ax1.set_xlim(50, 800)
    ax1.set_ylim(0.5, 42)
    ax1.set_xlabel('Enthalpie (kJ/kg)')
    ax1.set_ylabel('Pression (bar)')
    ax1.set_title('Diagramme Enthalpique du R290 (Propane) - Sans points (vierge)')
    ax1.legend(loc='upper right', bbox_to_anchor=(1, 1), fontsize='x-small')
    ax1.grid(True)

    # --- 2. Diagramme avec points du cycle (et valeurs sur les courbes iso) ---
    fig2, ax2 = plt.subplots(figsize=(12, 9))
    ax2.plot(h_liq, p_sat[:len(h_liq)], 'b-', linewidth=3, label='Saturation liquide (bulle)')
    ax2.plot(h_vap, p_sat[:len(h_vap)], 'r-', linewidth=3, label='Saturation vapeur (rosée)')

    for temp in range(-60, 100, 10):
        h_iso, p_iso = [], []
        for p in np.logspace(np.log10(0.5), np.log10(42), 300):
            try:
                t_bulb = PropsSI('T', 'P', p * 100000, 'Q', 0, 'R290') - 273.15
                t_dew = PropsSI('T', 'P', p * 100000, 'Q', 1, 'R290') - 273.15
                if t_bulb <= temp <= t_dew:
                    qualite = (temp - t_bulb) / (t_dew - t_bulb)
                    h = PropsSI('H', 'P', p * 100000, 'Q', qualite, 'R290') / 1000
                else:
                    h = PropsSI('H', 'T', temp + 273.15, 'P', p * 100000, 'R290') / 1000
                h_iso.append(h)
                p_iso.append(p)
            except ValueError:
                pass
        if h_iso and p_iso:
            ax2.plot(h_iso, p_iso, 'g--', linewidth=0.5)
            ax2.text(h_iso[-1] + 5, p_iso[-1], f'{temp}°C', fontsize=6, color='green', ha='right', va='center')

    for titre in np.arange(0.1, 1.0, 0.1):
        h_iso, p_iso = [], []
        for p in np.logspace(np.log10(0.5), np.log10(42), 300):
            try:
                h = PropsSI('H', 'P', p * 100000, 'Q', titre, 'R290') / 1000
                h_iso.append(h)
                p_iso.append(p)
            except ValueError:
                pass
        if h_iso and p_iso:
            ax2.plot(h_iso, p_iso, 'y:', linewidth=0.5)
            mid_index = len(h_iso) // 2
            ax2.text(h_iso[mid_index], p_iso[mid_index], f'x={titre:.1f}', fontsize=6, color='orange',
                    ha='center', va='center', bbox=dict(facecolor='white', edgecolor='none', alpha=0.7))

    for v in isochores:
        h_iso, p_iso = [], []
        for t in np.linspace(-60, 100, 200):
            try:
                p = PropsSI('P', 'T', t + 273.15, 'D', 1 / v, 'R290') / 100000
                h = PropsSI('H', 'T', t + 273.15, 'D', 1 / v, 'R290') / 1000
                h_iso.append(h)
                p_iso.append(p)
            except ValueError:
                pass
        if h_iso and p_iso:
            ax2.plot(h_iso, p_iso, 'm:', linewidth=0.5)
            ax2.text(h_iso[-1], p_iso[-1], f'{v:.3f}', fontsize=6, color='magenta', ha='left', va='top', rotation=10)

    for s in np.arange(1.8, 3.3, 0.1):
        h_iso, p_iso = [], []
        for t in np.linspace(-60, 100, 200):
            try:
                p = PropsSI('P', 'T', t + 273.15, 'S', s * 1000, 'R290') / 100000
                h = PropsSI('H', 'T', t + 273.15, 'S', s * 1000, 'R290') / 1000
                h_iso.append(h)
                p_iso.append(p)
            except ValueError:
                pass
        if h_iso and p_iso:
            ax2.plot(h_iso, p_iso, 'k:', linewidth=0.5)
            ax2.text(h_iso[-1], p_iso[-1], f'{s:.3f}', fontsize=6, color='black', ha='right', va='top', rotation=60)

    couleurs = ['cyan', 'magenta', 'green', 'orange', 'black', 'purple', 'brown']
    for i, pt in enumerate(points_info):
        enthalpie = pt[3]
        pression = pt[1]
        ax2.plot(enthalpie, pression, 'o', color=couleurs[i % len(couleurs)], markersize=10)
        ax2.text(enthalpie, pression, f'{i+1}', color=couleurs[i % len(couleurs)], fontsize=12, fontweight='bold')
    for i in range(len(points_info) - 1):
        ax2.plot([points_info[i][3], points_info[i+1][3]], [points_info[i][1], points_info[i+1][1]], '-', color='gray', linewidth=2)

    ax2.set_xscale('linear')
    ax2.set_yscale('log')
    ax2.set_xlim(50, 800)
    ax2.set_ylim(0.5, 42)
    ax2.set_xlabel('Enthalpie (kJ/kg)')
    ax2.set_ylabel('Pression (bar)')
    ax2.set_title('Diagramme Enthalpique du R290 (Propane) - Avec points du cycle')
    ax2.legend(loc='upper right', bbox_to_anchor=(1, 1), fontsize='x-small')
    ax2.grid(True)

    plt.show()






root = tk.Tk()
root.title("Cycle sur Diagramme Enthalpique du R290 - A gauche dans les cadres, saisissez vos mesures de pressions et températures aux 7 points proposés sur le schéma. Générez vos valeurs et vos affichages avec les boutons colorés de droite) ")
#root.state("zoomed")
# Création des widgets
labels = ["-1 Entrée Compresseur", "-2 Sortie Compresseur", "-3 Entrée Condenseur", "-4 Sortie Condenseur",
          "-5 Entrée Détendeur", "-6 Sortie Détendeur", "-7 Sortie Évaporateur (bulbe)"]
entries_p, entries_t = [], []

for i, label in enumerate(labels):
    tk.Label(root, text=f"P {label} (bar):").grid(row=i * 2, column=0, sticky='w', padx=5, pady=2)
    entry_p = tk.Entry(root, width=10)
    entry_p.grid(row=i * 2, column=1, padx=5, pady=2)
    entries_p.append(entry_p)

    tk.Label(root, text=f"T° {label} (°C):").grid(row=i * 2 + 1, column=0, sticky='w', padx=5, pady=2)
    entry_t = tk.Entry(root, width=10)
    entry_t.grid(row=i * 2 + 1, column=1, padx=5, pady=2)
    entries_t.append(entry_t)

# Affichage de la boite de dialogue
tk.Button(root, text="Tracer Diagramme", command=tracer_diagramme_enthalpique, bg='orange').grid(row=2, column=3,
                                                                                                    columnspan=1,
                                                                                                    pady=5)
tk.Button(root, text="Afficher Image", command=afficher_image, bg='orange').grid(row=4, column=3, columnspan=3, pady=5)
tk.Button(root, text="Afficher Graphique", command=afficher_graphique, bg='orange').grid(row=6, column=3,
                                                                                             pady=5)

# Ajout commande sous-refroidssment et surchauffe.
tk.Button(root, text="Surchauffe", command=calculer_surchauffe, bg='yellow').grid(row=7, column=3, columnspan=3, pady=5)
tk.Button(root, text="Sous-refroidissement", command=calculer_sousrefroidissement, bg='yellow').grid(row=8, column=3,
                                                                                               columnspan=1, pady=5)

                                                                                               # Ajout commande "Visualisation graphique"
tk.Button(root, text="Agrandissement\ndu diagramme", command=afficher_graphique_complet, bg='lightgreen').grid(row=12, column=3,
                                                                                               columnspan=1, pady=5)
tk.Button(root, text="Exportation\ndes données (Excel)", command=exporter_excel, bg='lightgreen').grid(row=13, column=3, columnspan=1, pady=5)
# Ajout commande "Impression en PDF de l'écran principal (format A4)
tk.Button(root, text="Sauvegarde\nPDF", command=sauvegarder_pdf, bg='lightgreen').grid(row=14, column=3, columnspan=1, pady=5)

# Ajouts des commande calcul surchauffe et sous-refroidissement.
tk.Button(root, text="COP", command=COP, fg="red", bg="black").grid(row=10, column=3, columnspan=3, pady=5)
tk.Button(root, text="EER", command=EER, fg="cyan", bg="black").grid(row=11, column=3, columnspan=1, pady=5)

info_label = tk.Label(root, text="", justify=tk.LEFT, font=('Courier', 16))
info_label.grid(row=17, column=0, columnspan=3, padx=10, pady=10, sticky='w')


image = Image.open(image_path)



image = image.resize((900, 550), Image.LANCZOS)
photo = ImageTk.PhotoImage(image)
image_label = tk.Label(root, image=photo)
image_label.image = photo
image_label.grid(row=0, column=2, rowspan=15, padx=10, pady=10, sticky="nsew")

# Création du widget canvas pour le graphique (mais ne pas l'afficher tout de suite)
fig, ax = plt.subplots(figsize=(20, 15), dpi=100)
canvas = FigureCanvasTkAgg(fig, master=root)
canvas_widget = canvas.get_tk_widget()

root.columnconfigure(2, weight=3)
root.rowconfigure(14, weight=1)

root.mainloop()
