/// @file   SmartGridModel.hpp
///

#ifndef MODEL_STATE_HPP
#define MODEL_STATE_HPP

#include <cstdlib>
#include <ctime>

#include "HardwareControl.hpp"
#include "ObserverPattern.hpp"
struct MaxPower
{
    static constexpr double village = 600;
    static constexpr double industry = 200;
    static constexpr double wind = 250;
    static constexpr double solar = 110;
};

constexpr double village_consumption_at[]{
    98, 95, 93, 94, 95, 101, 115,
    127, 132, 134, 136, 139, 138,
    136, 134, 132, 130, 132, 132,
    131, 125, 119, 114, 105, 98};

constexpr double sunnshine_percentage[]{
    0, 0, 0, 0, 0, 0, 3,
    12, 30, 52, 73, 88, 97,
    100, 98, 91, 81, 66, 46,
    25, 10, 2, 0, 0, 0};

constexpr double power_wind[]{
    0, 3, 25, 82, 174,
    321, 532, 815, 1180,
    1612, 1890, 2000, 2100};

struct CleanPower
{
    double solar = 0.0;
    double wind = 0.0;
};

struct PowerProduction
{
    double conventional;
    CleanPower renewable;
    double clean() { return renewable.solar + renewable.wind; }
    double sum() { return conventional + clean(); }
};

struct PowerUsage
{
    double village = 0.0;
    double industry = 0.0;
    double sum() { return village + industry; }
};


/// @brief Class representing the state of the Smart Grid Model and that has control over the hardware.
///
class SmartGridModel
{
public:
    SmartGridModel(HardwareControl &modell);

    // update modle state with new values
    void next_hour();

    // calculate model states
    void update_states();


    int get_time() const {return m_time;} // current time in hours [0-24]
    double get_sun() const {return m_sun;} // sunshine in [%]
    double get_wind() const {return m_wind;} // wind "speed"
    double get_excess_power() const {return m_excess_power;} // "available" power
    bool get_producing_state() const {return m_producing;} // returns if production is enabled

    double get_solar_park_size() const {return m_solar_size;} // "Size of the solar production plant"
    double get_wind_park_size() const {return m_windpark_size;} // "Size" of the windpark
    double get_village_size() const {return m_village_size;} // "Size of the village"

    PowerProduction get_power_production() const {return m_production;}
    PowerUsage get_power_usage() const {return m_usage;}

    void set_time(const int hour);
    void set_solar_size(const double solar_size) {if (solar_size >= 0) m_solar_size = solar_size;}
    void set_windpark_size(const double windpark_size) {if (windpark_size >= 0) m_windpark_size = windpark_size;}
    void set_village_size(const double village_size){ if(village_size >= 0) m_village_size = village_size;}
    void set_producing_state(const bool produce){m_producing = produce;}


private:
    void update_sun();
    void update_wind();
    void update_power_consumption();
    void update_power_production();
    void update_modell();
    void print_states();

    double calc_excess_power();

    double m_solar_size{15}; ///< scale for solar power production
    double m_windpark_size{3.0}; ///< scale the power production by wind 
    double m_village_size{10}; ///< scale how much power is used by the village

    int m_time{0};
    double m_sun{0};
    double m_wind{0};
    double m_excess_power{0.0};
    bool m_producing{false};
    
    PowerProduction m_production;
    PowerUsage m_usage;
    
    HardwareControl &m_modell;
};

#endif