from typing import List, Dict

class WaterHeater:
    def __init__(self, efficiency: float,
                 legal_temperature: float,
                 consumption_temperature: float,
                 people_number: int,
                 water_temperature: float,
                 daily_demand: float,
                 drawing_off_hour: int):
        self._efficiency: float = efficiency  # -
        self._legal_temperature: float = legal_temperature  # °C
        self._consumption_temperature: float = consumption_temperature  # °C
        self._people_number: float = people_number

        self._water_temperature: float = water_temperature  # °C
        self._daily_demand: float = daily_demand  # L, the individual hot water usage
        self._drawing_off_hour: int = drawing_off_hour  # h

        self._served_energy = 0  # kWh, the energy already served

        self._money_balance = 0  # €, the money earned at each time step
        self._energy_balance = 0  # kWh, the energy produced at each time step

    def _calculate_demand(self, t: int) -> float:
        water_cp = 4200 / 3.6e6  # kWh.kg-1.k-1
        density = 1  # kg.L-1

        DHW_consumption = self._daily_demand * (self._consumption_temperature - self._water_temperature) / (self._legal_temperature - self._water_temperature)  # L
        energy_demand = DHW_consumption * self._people_number * water_cp * density * (self._legal_temperature - self._water_temperature) / self._efficiency  # kWh
        energy_demand -= self._served_energy  # substraction of the energy already served

        return energy_demand

    def create_order(self, t: int) -> Dict:
        if t < self._drawing_off_hour:
            time_to_drawing_off = self._drawing_off_hour - t  # h, the remaining time before DHW is consumed
        else:
            time_to_drawing_off = 24 - (t - self._drawing_off_hour + 1)  # h, the remaining time before DHW is consumed
        price = 1.15 - 0.05 * time_to_drawing_off  # €/kWh

        order = {"order_type": "buy", "quantity": self._calculate_demand(t), "price": price}

        return order

    def update(self, market_result: Dict):
        quantity_bought = market_result["quantity"]  # kWh
        price = market_result["price"]  # €/kWh

        self._served_energy += quantity_bought  # updates the energy already served
        self._energy_balance += quantity_bought  # updates the energy consumed
        self._money_balance += quantity_bought * price  # updates the money spent

    # @property
    def get_money_balance(self):
        return self._money_balance

    # @property
    def get_energy_balance(self):
        return self._energy_balance
