"""
Parameter model class for atmospheric retrieval calculations.

This module contains the ParamForModel class which manages individual parameters
used in atmospheric retrieval models, including molecular species parameters,
atmospheric properties, and their constraints.
"""


class ParamForModel:
    """
    Manages individual parameters for atmospheric retrieval models.
    
    This class handles the storage, validation, and manipulation of individual
    parameters used in atmospheric retrieval calculations. It supports both
    fixed and variable parameters, molecular species handling, and boundary
    checking for retrieval algorithms.
    
    Attributes:
        name: Parameter name
        status: Whether parameter is variable (True) or fixed (False)
        scale: Parameter scaling factor
        constant_vmr: Whether volume mixing ratio is constant
        range_min: Minimum allowed parameter value
        range_max: Maximum allowed parameter value
        isotope: Isotope information
        is_molec: Whether parameter represents a molecular species
        molec_formula: Molecular formula if applicable
        mass: Molecular mass if applicable
        name_for_list_molec: Name used in molecular species lists
        starting_value_fixed: Fixed starting value
        starting_value_fixed_arr: Array of fixed starting values
        starting_value_variable: Variable starting value
        starting_value_variable_arr: Array of variable starting values
        value_in_retrieval: Current value during retrieval
        value_arr_in_retrieval: Array of values during retrieval
        sigma_prior: Prior uncertainty
        sigma_prior_arr: Array of prior uncertainties
    """
    
    def __init__(
        self,
        name,
        status,
        scale,
        constant_vmr,
        range_min,
        range_max,
        is_molec,
        molec_formula,
        mass,
        name_for_list_molec,
        isotope,
    ):
        """
        Initialize the ParamForModel object.
        
        Args:
            name: Parameter name
            status: Parameter status (True for variable, False for fixed)
            scale: Scaling factor for the parameter
            constant_vmr: Whether volume mixing ratio is constant
            range_min: Minimum allowed parameter value
            range_max: Maximum allowed parameter value
            is_molec: Whether parameter represents a molecular species
            molec_formula: Molecular formula (if molecular species)
            mass: Molecular mass (if molecular species)
            name_for_list_molec: Name for molecular species lists
            isotope: Isotope information
        """
        # Basic parameter properties
        self.name = name
        self.status = status
        self.scale = scale
        self.constant_vmr = constant_vmr
        self.range_min = range_min
        self.range_max = range_max
        self.isotope = isotope
        
        # Starting values for fixed parameters
        self.starting_value_fixed = None
        self.starting_value_fixed_arr = []
        
        # Starting values for variable parameters
        self.starting_value_variable = None
        self.starting_value_variable_arr = []
        
        # Values during retrieval process
        self.value_in_retrieval = None
        self.value_arr_in_retrieval = []
        
        # Prior uncertainty information
        self.sigma_prior = None
        self.sigma_prior_arr = []
        
        # Molecular species properties
        self.is_molec = is_molec
        self.molec_formula = molec_formula
        self.mass = mass
        self.name_for_list_molec = name_for_list_molec

    # STARTING VALUE MANAGEMENT METHODS
    
    def update_starting_value(self, value, sigma):
        """
        Update the starting value and prior uncertainty for the parameter.
        
        Args:
            value: New starting value
            sigma: Prior uncertainty (sigma)
        """
        if self.status:
            # Parameter is variable - update variable starting value
            self.starting_value_variable = value
        else:
            # Parameter is fixed - update fixed starting value
            self.starting_value_fixed = value
        
        # Update prior uncertainty
        self.sigma_prior = sigma

    def get_starting_value(self):
        """
        Get the current starting value based on parameter status.
        
        Returns:
            Starting value (variable if status=True, fixed if status=False)
        """
        if self.status:
            return self.starting_value_variable
        else:
            return self.starting_value_fixed

    def get_starting_value_arr(self):
        """
        Get the starting value array based on parameter status.
        
        Returns:
            Starting value array (variable if status=True, fixed if status=False)
        """
        if self.status:
            return self.starting_value_variable_arr
        else:
            return self.starting_value_fixed_arr

    # ARRAY MANAGEMENT METHODS
    
    def append_elem(self, value, sigma):
        """
        Append a value and sigma to the appropriate arrays.
        
        Args:
            value: Value to append
            sigma: Sigma value to append
        """
        if self.status:
            # Parameter is variable - append to variable array
            self.starting_value_variable_arr.append(value)
        else:
            # Parameter is fixed - append to fixed array
            self.starting_value_fixed_arr.append(value)
        
        # Always append sigma to sigma array
        self.sigma_prior_arr.append(sigma)

    # RETRIEVAL VALUE MANAGEMENT METHODS
    
    def get_retrieval_value(self):
        """
        Get the current retrieval value based on parameter status.
        
        Returns:
            Retrieval value (variable if status=True, fixed starting value if status=False)
        """
        if self.status:
            return self.value_in_retrieval
        else:
            return self.starting_value_fixed

    def get_retrieval_value_arr(self):
        """
        Get the retrieval value array based on parameter status.
        
        Returns:
            Retrieval value array (variable if status=True, fixed starting array if status=False)
        """
        if self.status:
            return self.value_arr_in_retrieval
        else:
            return self.starting_value_fixed_arr

    # VALIDATION METHODS
    
    def boundaries_check(self):
        """
        Check if parameter values are within specified boundaries.
        
        Returns:
            True if all values are within boundaries, False otherwise
        """
        cond = True
        
        if self.status:
            # Check boundaries for variable parameters
            if self.starting_value_variable is None:
                # Check array values if single value is not set
                for elem in self.value_arr_in_retrieval:
                    cond = cond and (self.range_min <= elem <= self.range_max)
            else:
                # Check single retrieval value
                cond = self.range_min <= self.value_in_retrieval <= self.range_max
            return cond
        else:
            # Fixed parameters always pass boundary check
            return cond

    # MOLECULAR SPECIES METHODS
    
    def is_molec_func(self):
        """
        Check if parameter represents a molecular species.
        
        Returns:
            True if parameter is a molecular species, False otherwise
        """
        return self.is_molec

    def molec_and_full_name(self):
        """
        Get molecular formula and full parameter name.
        
        Returns:
            Tuple containing (molecular_formula, parameter_name)
        """
        return self.molec_formula, self.name

    def is_VMR_costant(self):
        """
        Check if volume mixing ratio is constant.
        
        Returns:
            True if VMR is constant, False otherwise
        """
        return self.constant_vmr

    def get_mass(self):
        """
        Get the molecular mass.
        
        Returns:
            Molecular mass value
        """
        return self.mass

    # UNCERTAINTY METHODS
    
    def get_sigma_prior(self):
        """
        Get the prior uncertainty (sigma) value or array.
        
        Returns:
            Sigma array if starting_value_variable is None, single sigma value otherwise
        """
        if self.starting_value_variable is None:
            return self.sigma_prior_arr
        else:
            return self.sigma_prior
