"""
CoolProp Calculator for Thermoptim Integration
Provides thermodynamic property calculations using CoolProp library
"""

try:
    import CoolProp.CoolProp as CP
    from CoolProp.CoolProp import PropsSI
    COOLPROP_AVAILABLE = True
except ImportError:
    print("Warning: CoolProp not available. Install with: pip install CoolProp")
    COOLPROP_AVAILABLE = False

import math

class CoolPropCalculator:
    """
    Wrapper pour les calculs CoolProp
    """
    
    def __init__(self):
        self.available = COOLPROP_AVAILABLE
        if not self.available:
            raise ImportError("CoolProp library not available")
    
    def get_property(self, output_prop, input1_name, input1_value, 
                    input2_name, input2_value, fluid_name):
        """
        Calcule une propriété thermodynamique
        
        Args:
            output_prop: Propriété de sortie ('T', 'P', 'H', 'S', 'D', etc.)
            input1_name: Nom de la première propriété d'entrée
            input1_value: Valeur de la première propriété
            input2_name: Nom de la deuxième propriété d'entrée  
            input2_value: Valeur de la deuxième propriété
            fluid_name: Nom du fluide CoolProp
            
        Returns:
            float: Valeur de la propriété demandée
        """
        try:
            return PropsSI(output_prop, input1_name, input1_value, 
                          input2_name, input2_value, fluid_name)
        except Exception as e:
            raise Exception(f"CoolProp calculation failed: {e}")
    
    def get_temperature_from_enthalpy_pressure(self, h, P, fluid_name):
        """
        Calcule la température à partir de l'enthalpie et de la pression
        
        Args:
            h: Enthalpie massique (J/kg)
            P: Pression (Pa)
            fluid_name: Nom du fluide CoolProp
            
        Returns:
            float: Température (K)
        """
        return self.get_property('T', 'H', h, 'P', P, fluid_name)
    
    def get_enthalpy_from_temperature_pressure(self, T, P, fluid_name):
        """
        Calcule l'enthalpie à partir de la température et de la pression
        
        Args:
            T: Température (K)
            P: Pression (Pa)
            fluid_name: Nom du fluide CoolProp
            
        Returns:
            float: Enthalpie massique (J/kg)
        """
        return self.get_property('H', 'T', T, 'P', P, fluid_name)
    
    def get_entropy_from_temperature_pressure(self, T, P, fluid_name):
        """
        Calcule l'entropie à partir de la température et de la pression
        
        Args:
            T: Température (K)
            P: Pression (Pa)
            fluid_name: Nom du fluide CoolProp
            
        Returns:
            float: Entropie massique (J/kg/K)
        """
        return self.get_property('S', 'T', T, 'P', P, fluid_name)
    
    def get_density_from_temperature_pressure(self, T, P, fluid_name):
        """
        Calcule la densité à partir de la température et de la pression
        
        Args:
            T: Température (K)
            P: Pression (Pa)
            fluid_name: Nom du fluide CoolProp
            
        Returns:
            float: Densité (kg/m³)
        """
        return self.get_property('D', 'T', T, 'P', P, fluid_name)
    
    def get_cp_from_temperature_pressure(self, T, P, fluid_name):
        """
        Calcule la capacité calorifique à pression constante
        
        Args:
            T: Température (K)
            P: Pression (Pa)
            fluid_name: Nom du fluide CoolProp
            
        Returns:
            float: Cp (J/kg/K)
        """
        return self.get_property('C', 'T', T, 'P', P, fluid_name)
    
    def get_cv_from_temperature_pressure(self, T, P, fluid_name):
        """
        Calcule la capacité calorifique à volume constant
        
        Args:
            T: Température (K)
            P: Pression (Pa)
            fluid_name: Nom du fluide CoolProp
            
        Returns:
            float: Cv (J/kg/K)
        """
        return self.get_property('O', 'T', T, 'P', P, fluid_name)
    
    def get_saturation_temperature(self, P, fluid_name):
        """
        Calcule la température de saturation à une pression donnée
        
        Args:
            P: Pression (Pa)
            fluid_name: Nom du fluide CoolProp
            
        Returns:
            float: Température de saturation (K)
        """
        try:
            return PropsSI('T', 'P', P, 'Q', 0, fluid_name)
        except Exception as e:
            raise Exception(f"Saturation temperature calculation failed: {e}")
    
    def get_saturation_pressure(self, T, fluid_name):
        """
        Calcule la pression de saturation à une température donnée
        
        Args:
            T: Température (K)
            fluid_name: Nom du fluide CoolProp
            
        Returns:
            float: Pression de saturation (Pa)
        """
        try:
            return PropsSI('P', 'T', T, 'Q', 0, fluid_name)
        except Exception as e:
            raise Exception(f"Saturation pressure calculation failed: {e}")
    
    def get_critical_properties(self, fluid_name):
        """
        Obtient les propriétés critiques d'un fluide
        
        Args:
            fluid_name: Nom du fluide CoolProp
            
        Returns:
            dict: Dictionnaire avec Tc, Pc, rhoc
        """
        try:
            Tc = PropsSI('Tcrit', fluid_name)
            Pc = PropsSI('Pcrit', fluid_name)
            rhoc = PropsSI('rhocrit', fluid_name)
            return {'Tc': Tc, 'Pc': Pc, 'rhoc': rhoc}
        except Exception as e:
            raise Exception(f"Critical properties calculation failed: {e}")
    
    def list_available_fluids(self):
        """
        Liste les fluides disponibles dans CoolProp
        
        Returns:
            list: Liste des noms de fluides
        """
        if not self.available:
            return []
        
        try:
            return CP.get_global_param_string("FluidsList").split(',')
        except Exception:
            # Liste de base si l'API échoue
            return ['Water', 'CO2', 'Nitrogen', 'Oxygen', 'Hydrogen', 
                   'Methane', 'Ethane', 'Propane', 'Butane', 'Ammonia',
                   'R134a', 'R410A', 'R22', 'Air']

# Fonctions globales pour l'interface JPype
calculator = None

def initialize():
    """Initialise le calculateur CoolProp"""
    global calculator
    if calculator is None:
        calculator = CoolPropCalculator()
    return calculator.available

def calculate_property(output_prop, input1_name, input1_value, 
                      input2_name, input2_value, fluid_name):
    """Interface globale pour le calcul de propriétés"""
    global calculator
    if calculator is None:
        initialize()
    
    return calculator.get_property(output_prop, input1_name, input1_value,
                                  input2_name, input2_value, fluid_name)

def get_temperature_from_hp(h, P, fluid_name):
    """Calcule T à partir de h et P - Interface simplifiée"""
    global calculator
    if calculator is None:
        if not initialize():
            raise Exception("CoolProp not available")
    
    return calculator.get_temperature_from_enthalpy_pressure(h, P, fluid_name)

def get_enthalpy_from_tp(T, P, fluid_name):
    """Calcule h à partir de T et P - Interface simplifiée"""
    global calculator
    if calculator is None:
        if not initialize():
            raise Exception("CoolProp not available")
    
    return calculator.get_enthalpy_from_temperature_pressure(T, P, fluid_name)

def get_all_properties(T, P, fluid_name):
    """
    Calcule toutes les propriétés principales pour T et P donnés
    
    Returns:
        dict: Dictionnaire avec h, s, rho, cp, cv
    """
    global calculator
    if calculator is None:
        initialize()
    
    try:
        h = calculator.get_enthalpy_from_temperature_pressure(T, P, fluid_name)
        s = calculator.get_entropy_from_temperature_pressure(T, P, fluid_name)
        rho = calculator.get_density_from_temperature_pressure(T, P, fluid_name)
        cp = calculator.get_cp_from_temperature_pressure(T, P, fluid_name)
        cv = calculator.get_cv_from_temperature_pressure(T, P, fluid_name)
        
        return {
            'h': h,
            's': s,
            'rho': rho,
            'cp': cp,
            'cv': cv
        }
    except Exception as e:
        raise Exception(f"Properties calculation failed: {e}")

# Interface ligne de commande
if __name__ == "__main__":
    import sys
    
    if len(sys.argv) > 1:
        # Mode ligne de commande
        command = sys.argv[1]
        
        if command == "get_temperature_from_hp" and len(sys.argv) == 5:
            h = float(sys.argv[2])
            P = float(sys.argv[3])
            fluid = sys.argv[4]
            result = get_temperature_from_hp(h, P, fluid)
            print(result)
            
        elif command == "get_enthalpy_from_tp" and len(sys.argv) == 5:
            T = float(sys.argv[2])
            P = float(sys.argv[3])
            fluid = sys.argv[4]
            result = get_enthalpy_from_tp(T, P, fluid)
            print(result)
            
        elif command == "calculate_property" and len(sys.argv) >= 8:
            output_prop = sys.argv[2]
            input1_name = sys.argv[3]
            input1_value = float(sys.argv[4])
            input2_name = sys.argv[5]
            input2_value = float(sys.argv[6])
            fluid = sys.argv[7]
            result = calculate_property(output_prop, input1_name, input1_value,
                                      input2_name, input2_value, fluid)
            print(result)
            
        else:
            print("Usage: python coolprop_calculator.py <command> <args>")
            sys.exit(1)
    else:
        # Mode test
        if COOLPROP_AVAILABLE:
            calc = CoolPropCalculator()
            T = 373.15
            P = 101325
            print("Test CoolProp Calculator:")
            print(f"Fluid: Water, T = {T} K, P = {P} Pa")
            try:
                h = calc.get_enthalpy_from_temperature_pressure(T, P, 'Water')
                print(f"Enthalpy: {h/1000:.2f} kJ/kg")
                T_calc = calc.get_temperature_from_enthalpy_pressure(h, P, 'Water')
                print(f"Temperature from h,P: {T_calc:.2f} K")
            except Exception as e:
                print(f"Error: {e}")
        else:
            print("CoolProp not available - install with: pip install CoolProp")