/***************************** LICENSE START ***********************************

 Copyright 2012 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

#include "Metview.h"

#include "MvFlextra.h"

#include <iostream>
#include <stdexcept>


class Base : public MvService
{
protected:
    Base(const char* a) :
        MvService(a) {}
};


class FlextraVisualiser : public Base
{
public:
    FlextraVisualiser(const char* a) :
        Base(a) {}
    void serve(MvRequest&, MvRequest&) override;
};

void FlextraVisualiser::serve(MvRequest& in, MvRequest& out)
{
    std::cout << "--------------FlextraVisualiser::serve()--------------" << std::endl;
    in.print();

    MvRequest inR = in;
    std::string inFile;
    std::string verb = in.getVerb();

    //------------------------------------------
    // Find out the input filename
    //------------------------------------------

    MvRequest dataR = inR("FLEXTRA_DATA");
    const char* iconType = dataR.getVerb();

    // If no icon is specified
    if (!iconType) {
        // If no path is there either
        const char* path = inR("FLEXTRA_FILENAME");
        if (!path || strcmp(path, "OFF") == 0) {
            marslog(LOG_EROR, "No data icon or path is specified!");
            setError(13);
            return;
        }
        else {
            inFile = std::string(path);
        }
    }
    else {
        const char* path = dataR("PATH");
        if (!path) {
            marslog(LOG_EROR, "No path is specified for FLEXTRA_FILE icon!");
            setError(13);
            return;
        }

        inFile = std::string(path);
    }


    const char* plot_type = inR("FLEXTRA_PLOT_TYPE");
    if (!plot_type) {
        marslog(LOG_EROR, "No parameter FLEXTRA_PLOT_TYPE is specified!");
        setError(13);
        return;
    }

    const char* plot_mode = inR("FLEXTRA_PLOT_CONTENT");
    if (!plot_mode) {
        marslog(LOG_EROR, "No parameter FLEXTRA_PLOT_MODE is specified!");
        setError(13);
        return;
    }


    //----------------------------------
    // Decode
    //----------------------------------

    MvFlextra flextra(inFile);

    int blockNum = flextra.blockNum();

    if (blockNum == 0) {
        marslog(LOG_EROR, "No trajectories were found in input file!");
        setError(13);
        return;
    }

    //----------------------------------
    // Select block
    //----------------------------------

    MvFlextraBlock* data = nullptr;
    const char* blockIdChar = inR("FLEXTRA_GROUP_INDEX");
    if (blockIdChar) {
        int blockId = atoi(blockIdChar) - 1;
        if (blockId >= 0 && blockId < blockNum) {
            data = flextra.blocks().at(blockId);
        }
        else {
            marslog(LOG_EROR, "Could not find the specified block (%d) in trajectory file!", blockId + 1);
            setError(13);
            return;
        }
    }
    else {
        marslog(LOG_EROR, "No parameter FLEXTRA_GROUP_INDEX is specified!");
        setError(13);
        return;
    }

    //----------------------------------
    // Check trajectory num
    //----------------------------------

    int trNum = data->itemNum();
    if (trNum == 0) {
        marslog(LOG_EROR, "No trajectories were found in selected block!");
        setError(13);
        return;
    }

    //----------------------------------
    // Points file
    //----------------------------------

    std::string outFilePoints(marstmp());
    int metaDataCntPoints = 0;

    // data->writeAll(outFilePoints,metaDataCntPoints);

    // Requests

    if (strcmp(plot_type, "GEO_POINTS") == 0) {
        if (strcmp(plot_mode, "TRAJECTORY") == 0) {
            data->writeAll(outFilePoints, metaDataCntPoints);

            MvRequest req("TABLE_GEO_POINTS");
            req("TABLE_PLOT_TYPE") = "GEO_POINTS";
            req("TABLE_FILENAME") = outFilePoints.c_str();
            req("TABLE_VARIABLE_IDENTIFIER_TYPE") = "INDEX";
            req("TABLE_LONGITUDE_VARIABLE") = 4;
            req("TABLE_LATITUDE_VARIABLE") = 5;
            req("TABLE_VALUE_VARIABLE") = 1;
            req("TABLE_DELIMITER") = ",";
            req("TABLE_COMBINE_DELIMITERS") = "OFF";
            req("TABLE_HEADER_ROW") = 0;
            req("TABLE_DATA_ROW_OFFSET") = metaDataCntPoints + 1;  // 3;

            for (int i = 0; i < metaDataCntPoints; i++) {
                req.addValue("TABLE_META_DATA_ROWS", i + 1);
            }

            out = req;

            MvRequest vdef("MSYMB");
            vdef("LEGEND") = "ON";
            vdef("SYMBOL_TYPE") = "MARKER";
            vdef("SYMBOL_TABLE_MODE") = "ADVANCED";
            vdef("SYMBOL_ADVANCED_TABLE_SELECTION_TYPE") = "INTERVAL";
            vdef("SYMBOL_ADVANCED_TABLE_MIN_VALUE") = 1;
            vdef("SYMBOL_ADVANCED_TABLE_MAX_VALUE") = trNum + 1;  //!!
            vdef("SYMBOL_ADVANCED_TABLE_INTERVAL") = 1;

            for (int i = 0; i < 9; i++) {
                vdef.addValue("SYMBOL_ADVANCED_TABLE_MARKER_LIST", i);
            }

            vdef("SYMBOL_ADVANCED_TABLE_HEIGHT_LIST") = 0.3;
            vdef("SYMBOL_CONNECT_LINE") = "ON";
            vdef("SYMBOL_CONNECT_AUTOMATIC_LINE_COLOUR") = "ON";
            vdef("SYMBOL_ADVANCED_TABLE_COLOUR_DIRECTION") = "CLOCKWISE";
            vdef("_CLASS") = "MSYMB";
            vdef("_NAME") = "MSYMB0";

            out = out + vdef;
        }
        else if (strcmp(plot_mode, "LABEL") == 0) {
            std::vector<std::string> labels;
            data->writeLabels(outFilePoints, metaDataCntPoints, "6h", labels);

            MvRequest req("TABLE_GEO_POINTS");
            req("TABLE_PLOT_TYPE") = "GEO_POINTS";
            req("TABLE_FILENAME") = outFilePoints.c_str();
            req("TABLE_VARIABLE_IDENTIFIER_TYPE") = "INDEX";
            req("TABLE_LONGITUDE_VARIABLE") = 3;
            req("TABLE_LATITUDE_VARIABLE") = 4;
            req("TABLE_VALUE_VARIABLE") = "";
            req("TABLE_DELIMITER") = ",";
            req("TABLE_COMBINE_DELIMITERS") = "OFF";
            req("TABLE_HEADER_ROW") = 0;
            req("TABLE_DATA_ROW_OFFSET") = metaDataCntPoints + 1;  // 3;

            for (int i = 0; i < metaDataCntPoints; i++) {
                req.addValue("TABLE_META_DATA_ROWS", i + 1);
            }

            out = req;

            MvRequest vdef("MSYMB");
            vdef("LEGEND") = "OFF";
            // vdef("SYMBOL_TYPE") = "NUMBER";
            // vdef("FORMAT") = "(F4.2)";
            // vdef("_CLASS")="MSYMB";
            // vdef("_NAME")="MSYMB0";

            vdef("SYMBOL_TYPE") = "TEXT";
            vdef("SYMBOL_TABLE_MODE") = "ADVANCED";
            /*vdef("SYMBOL_ADVANCED_TABLE_SELECTION_TYPE") = "INTERVAL";
            vdef("SYMBOL_ADVANCED_TABLE_MIN_VALUE") = 1;
            vdef("SYMBOL_ADVANCED_TABLE_MAX_VALUE") = trNum+1; //!!
            vdef("SYMBOL_ADVANCED_TABLE_INTERVAL") = 1;*/

            for (auto& label : labels) {
                vdef.addValue("SYMBOL_ADVANCED_TABLE_TEXT_LIST", label.c_str());
            }

            vdef("SYMBOL_ADVANCED_TABLE_TEXT_HEIGHT") = 0.3;
            vdef("SYMBOL_ADVANCED_TABLE_TEXT_HEIGHT") = 0.3;

            vdef("SYMBOL_ADVANCED_TABLE_COLOUR_DIRECTION") = "CLOCKWISE";
            vdef("_CLASS") = "MSYMB";
            vdef("_NAME") = "MSYMB0";

            out = out + vdef;

            /*const char *period=inR("FLEXTRA_LABEL_PERIOD");
            std::string periodStr(period);

            std::string outFileLabels(marstmp());
            int metaDataCnt=0;

            data->writeLabels(outFileLabels,metaDataCnt,period);


            MvRequest req("TABLE_GEO_POINTS");
            req("TABLE_PLOT_TYPE")="GEO_POINTS";
            req("TABLE_FILENAME")=outFileLabels.c_str();
            req("TABLE_VARIABLE_IDENTIFIER_TYPE")="INDEX";
            req("TABLE_LONGITUDE_VARIABLE")=3;
            req("TABLE_LATITUDE_VARIABLE")=4;
            req("TABLE_VALUE_VARIABLE")=1;
            req("TABLE_DELIMITER")=",";
            req("TABLE_COMBINE_DELIMITERS")="OFF";
            req("TABLE_HEADER_ROW") = 0;
            req("TABLE_DATA_ROW_OFFSET") =  metaDataCnt+1;//3;

            out=req;




            MvRequest vdef("MSYMB");
            vdef("LEGEND") = "OFF";
            vdef("SYMBOL_TYPE") = "NUMBER";

            out=out+vdef;*/
        }

        out("_VERB") = "TABLE_GEO_POINTS";
    }

    else if (strcmp(plot_type, "XY_POINTS") == 0) {
        const char* x_var = inR("FLEXTRA_X_VARIABLE");
        const char* y_var = inR("FLEXTRA_Y_VARIABLE");

        if (!x_var || !y_var) {
            setError(13);
            return;
        }


        if (strcmp(plot_mode, "TRAJECTORY") == 0) {
            data->writeAll(outFilePoints, metaDataCntPoints);

            std::map<std::string, int> parId;
            parId["DATE"] = 2;
            parId["LATITUDE"] = 4;
            parId["LONGITUDE"] = 5;
            parId["ETA"] = 6;
            parId["PRESSURE"] = 7;
            parId["HEIGHT"] = 8;
            parId["HEIGHT_AGL"] = 9;
            parId["PV"] = 10;

            MvRequest req("TABLE_XY_POINTS");
            req("TABLE_PLOT_TYPE") = "XY_POINTS";
            req("TABLE_FILENAME") = outFilePoints.c_str();
            req("TABLE_VARIABLE_IDENTIFIER_TYPE") = "INDEX";

            if (strcmp(x_var, "DATE") == 0) {
                req("TABLE_X_TYPE") = "DATE";
            }
            req("TABLE_X_VARIABLE") = parId[std::string(x_var)];

            if (strcmp(y_var, "DATE") == 0) {
                req("TABLE_Y_TYPE") = "DATE";
            }
            req("TABLE_Y_VARIABLE") = parId[std::string(y_var)];

            req("TABLE_VALUE_VARIABLE") = "1";
            req("TABLE_DELIMITER") = ",";
            req("TABLE_COMBINE_DELIMITERS") = "OFF";
            req("TABLE_HEADER_ROW") = 0;
            req("TABLE_DATA_ROW_OFFSET") = metaDataCntPoints + 1;
            for (int i = 0; i < metaDataCntPoints; i++) {
                req.addValue("TABLE_META_DATA_ROWS", i + 1);
            }

            out = req;

            MvRequest vdef("MSYMB");
            vdef("LEGEND") = "ON";
            vdef("SYMBOL_TYPE") = "MARKER";
            vdef("SYMBOL_TABLE_MODE") = "ADVANCED";
            vdef("SYMBOL_ADVANCED_TABLE_SELECTION_TYPE") = "INTERVAL";
            vdef("SYMBOL_ADVANCED_TABLE_MIN_VALUE") = 1;
            vdef("SYMBOL_ADVANCED_TABLE_MAX_VALUE") = trNum + 1;  //!!
            vdef("SYMBOL_ADVANCED_TABLE_INTERVAL") = 1;

            for (int i = 0; i < 9; i++) {
                vdef.addValue("SYMBOL_ADVANCED_TABLE_MARKER_LIST", i);
            }

            vdef("SYMBOL_ADVANCED_TABLE_HEIGHT_LIST") = 0.3;
            vdef("SYMBOL_CONNECT_LINE") = "ON";
            vdef("SYMBOL_CONNECT_AUTOMATIC_LINE_COLOUR") = "ON";
            vdef("SYMBOL_ADVANCED_TABLE_COLOUR_DIRECTION") = "CLOCKWISE";
            vdef("_CLASS") = "MSYMB";
            vdef("_NAME") = "MSYMB0";

            out = out + vdef;

            /*MvRequest vdef("MGRAPH");
            vdef("LEGEND") = "ON";
            vdef("GRAPH_LINE") = "ON";
            out=out+vdef;*/
        }

        out("_VERB") = "TABLE_XY_POINTS";
    }

    //----------------------------------
    // Symbol highlight
    //----------------------------------

    /*const char *highlight=in("FLEXTRA_SYMBOL_HIGHLIGHT");

    if(highlight && strcmp(highlight,"ON") == 0)
    {
        const char *period=inR("FLEXTRA_SYMBOL_HIGHLIGHT_PERIOD");
        std::string periodStr(period);

        std::string outFileHighlight(marstmp());
        int metaDataCnt=0;

        data->writeHighlightPoints(outFileHighlight,metaDataCnt,periodStr);

        //Requests

        if(strcmp(plot_type,"GEO_POINTS") == 0)
        {
            MvRequest req("TABLE_GEO_POINTS");
            req("TABLE_PLOT_TYPE")="GEO_POINTS";
            req("TABLE_FILENAME")=outFileHighlight.c_str();
            req("TABLE_VARIABLE_IDENTIFIER_TYPE")="INDEX";
            req("TABLE_LONGITUDE_VARIABLE")=3;
            req("TABLE_LATITUDE_VARIABLE")=4;
            req("TABLE_VALUE_VARIABLE")=1;
            req("TABLE_DELIMITER")=",";
            req("TABLE_COMBINE_DELIMITERS")="OFF";
            req("TABLE_HEADER_ROW") = 0;
            req("TABLE_DATA_ROW_OFFSET") =  metaDataCnt+1;//3;


            MvRequest vdef("MSYMB");
            //vdef("LEGEND") = "ON";
            vdef("SYMBOL_TYPE") = "MARKER";
            vdef("SYMBOL_TABLE_MODE") = "ADVANCED";
            //vdef("SYMBOL_OUTLINE") = "ON";
            vdef("SYMBOL_ADVANCED_TABLE_SELECTION_TYPE") = "INTERVAL";
            vdef("SYMBOL_ADVANCED_TABLE_MIN_VALUE") = 1;
            vdef("SYMBOL_ADVANCED_TABLE_MAX_VALUE") = trNum+1;
            vdef("SYMBOL_ADVANCED_TABLE_INTERVAL") = 1;
            for(int i=0; i < 9; i++)
            {
                vdef.addValue("SYMBOL_ADVANCED_TABLE_MARKER_LIST",i);
            }

            //vdef("SYMBOL_ADVANCED_TABLE_MARKER_LIST") = 15;
            vdef("SYMBOL_ADVANCED_TABLE_HEIGHT_LIST") = 0.6;
            vdef("SYMBOL_ADVANCED_TABLE_COLOUR_DIRECTION") = "CLOCKWISE";

            out=out+req;
            out=out+vdef;
        }
    }
    */

    MvRequest legReq("MLEGEND");
    legReq("LEGEND_DISPLAY_TYPE") = "DISJOINT";

    out = out + legReq;

    out.print();


    // system(cmd.c_str());
}


int main(int argc, char** argv)
{
    MvApplication theApp(argc, argv);

    FlextraVisualiser flextra("FLEXTRA_VISUALISER");

    theApp.run();
}
