/* @@tagdepends: @@endtagdepends
   @@tagdynamic@@ */

#include <vle/devs/Dynamics.hpp>
#include <vle/utils/Package.hpp>

#include <fstream>
#include <sstream>
#include <iostream>
#include<boost/algorithm/string.hpp>
#include<cstdlib>


namespace malariaspread  {

class Meteo : public vle::devs::Dynamics
{
    enum State { STATE1, STATE2 };

    // Phase du modèle
    State state;

    // Working variables
    std::ifstream file;
    std::string line;

    // Parameters
    std::string file_path;

    //! Variables d'état du modèle
    int year;
    int month;
    int day;
    double Tmin;
    double Tmax;
    double Tmoy;
    double Hmin;
    double Hmax;
    double Hmoy;

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

        std::stringstream ss(line);
        double x;
std::vector <std::string> V;
boost::split(V, line,boost::is_any_of(","));

 //std::cout<<year;  std::cout<<"| "; std::cout<<month; std::cout<< "| "; std::cout<<day<<std::endl;

        year=atof(V[0].c_str());
        month=atof(V[1].c_str());
        day=atof(V[2].c_str());
        Tmax=atof(V[3].c_str());
        Tmoy=atof(V[4].c_str());
        Tmin=atof(V[5].c_str());
        x=atof(V[6].c_str());
        x=atof(V[7].c_str());
        x=atof(V[8].c_str());
        Hmax=atof(V[9].c_str());
        Hmoy=atof(V[10].c_str());
        Hmin=atof(V[11].c_str());

 //std::cout<<year;  std::cout<<"| "; std::cout<<month; std::cout<< "| "; std::cout<<day<<std::endl;

    }

public:
     Meteo(const vle::devs::DynamicsInit& model,
           const vle::devs::InitEventList& events) :
        vle::devs::Dynamics(model, events)
    {
        file_path = vle::value::toString(events.get("meteo_file"));
    }

    virtual ~Meteo()
    {
    }

    vle::devs::Time timeAdvance() const
    {
        switch (state) {
        case STATE2:
            return 1.0;
        case STATE1:
            return 0.0;
        default:
            return vle::devs::infinity;
        }
    }

    vle::devs::Time init(const vle::devs::Time& /*time*/)
    {
        vle::utils::Package p("malariaspread");
        state = STATE1;
        file.open(p.getDataFile(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 internalTransition(const vle::devs::Time& /*time*/)
    {
        switch (state) {
        case STATE2 :
            updateState();
            state = STATE1;
            break;
        case STATE1:
            state = STATE2;
            break;
        }
    }

    void output(const vle::devs::Time& /* time */,
                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.push_back(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.push_back(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.push_back(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.push_back(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.push_back(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.push_back(ee);
            }
        }
    }

    vle::value::Value* 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);
        return 0;
    }
};

} // namespace malariaspread

DECLARE_DYNAMICS(malariaspread::Meteo)
