#include "Meteo.hpp"

#include <vle/utils/Exception.hpp>

Meteo::Meteo(const vle::graph::AtomicModel& model,
             const vle::devs::InitEventList& lst) :
    vle::devs::Dynamics(model, lst)
{
    file_path = vle::value::toString(lst.get("meteo_file"));
}

Meteo::~Meteo()
{
}

vle::devs::Time Meteo::timeAdvance() const
{
    switch (state) {
    case STATE2:
        return 1.0;
    case STATE1:
        return 0.0;
    default:
        Throw(vle::utils::InternalError, "Meteo::timeAdvance()");
    }
}

vle::devs::Time Meteo::init(const vle::devs::Time& /*time*/)
{
    state = STATE1;
    file.open(file_path.c_str());

    // skip first line (header)
    if (file.good()) {
        getline(file, line);
    }
    year = 0;
    month = 0;
    day = 0;
    Tmin = 0;
    Tmax = 0;
    Tmoy = 0;
    Hmin = 0;
    Hmax = 0;
    Hmoy = 0;
    return 0.0;
}

void Meteo::internalTransition(const vle::devs::Time& /*time*/)
{
    switch (state) {
    case STATE2 :
        updateState();
        state = STATE1;
        break;
    case STATE1:
        state = STATE2;
        break;
    default:
        Throw(vle::utils::InternalError, "Meteo::internalTransition");
    }
}

void  Meteo::output(const vle::devs::Time& currentTime,
                    vle::devs::ExternalEventList& output) const
{
    if (state == STATE1) {
        {
            vle::devs::ExternalEvent* ee = new vle::devs::ExternalEvent("Tmin");
            ee << vle::devs::attribute("name", buildString("Tmin"));
            ee << vle::devs::attribute("value", buildDouble(Tmin));
            output.addEvent(ee);
        }
        {
            vle::devs::ExternalEvent* ee = new vle::devs::ExternalEvent("Tmax");
            ee << vle::devs::attribute("name", buildString("Tmax"));
            ee << vle::devs::attribute("value", buildDouble(Tmax));
            output.addEvent(ee);
        }
        {
            vle::devs::ExternalEvent* ee = new vle::devs::ExternalEvent("Tmoy");
            ee << vle::devs::attribute("name", buildString("Tmoy"));
            ee << vle::devs::attribute("value", buildDouble(Tmoy));
            output.addEvent(ee);
        }
        {
            vle::devs::ExternalEvent* ee = new vle::devs::ExternalEvent("Hmin");
            ee << vle::devs::attribute("name", buildString("Hmin"));
            ee << vle::devs::attribute("value", buildDouble(Hmin));
            output.addEvent(ee);
        }
        {
            vle::devs::ExternalEvent* ee = new vle::devs::ExternalEvent("Hmax");
            ee << vle::devs::attribute("name", buildString("Hmax"));
            ee << vle::devs::attribute("value", buildDouble(Hmax));
            output.addEvent(ee);
        }
        {
            vle::devs::ExternalEvent* ee = new vle::devs::ExternalEvent("Hmoy");
            ee << vle::devs::attribute("name", buildString("Hmoy"));
            ee << vle::devs::attribute("value", buildDouble(Hmoy));
            output.addEvent(ee);
        }
    }
}


vle::value::Value* Meteo::observation(const vle::devs::ObservationEvent& event) const
{
    if (event.onPort("obs_m_Tx"))
        return buildDouble(Tmax);

    if (event.onPort("obs_m_Tn"))
        return buildDouble(Tmin);

    if (event.onPort("obs_m_Tmoy"))
        return buildDouble(Tmoy);

    if (event.onPort("obs_m_Hx"))
        return buildDouble(Hmax);

    if (event.onPort("obs_m_Hn"))
        return buildDouble(Hmin);

    if (event.onPort("obs_m_Hmoy"))
        return buildDouble(Hmoy);
}

void Meteo::updateState()
{
    if (file.good()) {
        getline(file, line);
    }

    std::stringstream ss(line);
    double x;

    ss >> year;
    ss >> month;
    ss >> day;
    ss >> Tmax;
    ss >> Tmoy;
    ss >> Tmin;
    ss >> x;
    ss >> x;
    ss >> x;
    ss >> Hmax;
    ss >> Hmoy;
    ss >> Hmin;
}
