"""
Modules for defining mediums used in thermal energy systems.
Author: Martin Altenburger, Paul Seidel
"""

from typing import Optional
from enum import Enum
from pydantic import BaseModel
from loguru import logger


class Medium(Enum):
    """
    Enum class for the mediums
    TODO: Add more mediums
    """

    WATER = "water"


class MediumParameters(BaseModel):
    """
    Base class for the medium parameters
    """

    cp: float
    rho: float


MEDIUM_VALUES = {Medium.WATER: MediumParameters(cp=4.19, rho=997)}


def get_medium_parameter(
    medium: Medium, temperature: Optional[float] = None
) -> MediumParameters:
    """Function to get the medium parameter
       - const values, if no temperature is set
       - calculation of cp and rho (constant pressure) as approximation of Glück
           - https://berndglueck.de/stoffwerte.php
           - "Zustandswerte Luft Wasser Dampf"  ISBN 3-345-00487-9

    Args:
        medium (Mediums): The medium
        temperature : float = None

    Returns:
        MediumParameters: The parameters of the medium
    """
    if medium not in MEDIUM_VALUES:
        logger.error(f"Medium {medium} not available")
        raise ValueError(f"Medium {medium} not available")

    if temperature is None:
        return MEDIUM_VALUES[medium]

    if medium is Medium.WATER:
        if temperature <= 0.1:
            logger.error("Attention! Temperature to low!")
            values = MediumParameters(cp=None, rho=None)
        elif temperature > 99.0:
            logger.error("Attention! Temperature to hight!")
            values = MediumParameters(cp=None, rho=None)
        else:
            # rho aproximation of Glück [kg/m³]:
            rho_calc = (
                1.002045 * 1000
                - 1.029905 * 0.1 * temperature
                - 3.698162 * 0.001 * temperature**2
                + 3.991053 * 0.000001 * temperature**3
            )
            # cp aproximation of Glück [kJ/kgK]:
            cp_calc = (
                4.177375
                - 2.144614 * 0.000001 * temperature
                - 3.165823 * 0.0000001 * temperature**2
                + 4.134309 * 0.00000001 * temperature**3
            )
            values = MediumParameters(cp=cp_calc, rho=rho_calc)

        return values
    # TODO add more mediums
    logger.error("Medium is not supported for temperature calculation")
    raise ValueError("Medium is not supported for temperature calculation")
