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

 Copyright 2022 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 "uPlotManager.hpp"

#include <iostream>
#include <memory>
#include <map>
#include <string>
#include <cstdlib>
#include <cstdio>

#include "uPlotService.hpp"
#include "MvMiscellaneous.h"

#ifdef METVIEW_ODB_NEW
#include "MvOdb.h"
#endif

using uPlotManagerPtr = std::shared_ptr<uPlotManager>;

uPlotManager::uPlotManager(const char* kw) :
    MvService(kw)
{
    saveToPool(false);
}

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

    // Priority 1: the Macro plot command
    // Priority 2: the context menu user option
    bool metzoom;
    if ((const char*)in("_MACRO_PLOT_COMMAND") && strcmp((const char*)in("_MACRO_PLOT_COMMAND"), "metzoom") == 0)
        metzoom = true;
    else if ((const char*)in("_MACRO_PLOT_COMMAND") && strcmp((const char*)in("_MACRO_PLOT_COMMAND"), "plot") == 0)
        metzoom = false;
    else if ((const char*)in("_ACTION") && strcmp((const char*)in("_ACTION"), "metzoom") == 0)
        metzoom = true;
    else
        metzoom = false;

    if (metzoom) {
        // FAMI20191120 I prefer to use the two commands below instead of CallMetZoom.
        // Because output with verb METZOOM would trigger module metzoom to be called.
        // It is working if a call comes from Desktop (user selects option METZOOM from
        // a dataunit icon).
        // But it is not working if a call comes from a Macro. The problem is that
        // function MetviewTask::reply(const Request& r, int) (directory Desktop/
        // MetviewTask.cc) receives an empty request. It would work if Request r
        // has the contents of variable out below.
        //
        // out = in;
        // out.setVerb("METZOOM");

        uPlotService::Instance().CallMetZoom(in, out);
    }
    else
        uPlotService::Instance().CalluPlot(in, out);

    // Send error message signal to the caller (i.e. Desktop)
    // The request out is not enough to tell Desktop that an error
    // ocurred. Function MvProtocol::setError needs to be called too.
    if (const char* verbCh = out.getVerb()) {
        if (strcmp(verbCh, "ERROR") == 0) {
            if ((const char*)out("MESSAGE"))
                setError(1, "%s", (const char*)out("MESSAGE"));
            else
                setError(1);
        }
    }

    std::cout << "uPlotManager::serve --> out" << std::endl;
    out.print();

    return;
}

//--------------------------------------------------------

int main(int argc, char** argv)
{
    // Set option -debug to true
    // This is needed in order to force the Save Request command
    // to save the hidden parameters too (underscore parameters)
    option opts[] = {"debug", "MARS_DEBUG", "-debug", "1", t_boolean, sizeof(boolean), OFFSET(globals, debug)};

    MvApplication theApp(argc, argv, nullptr, &mars, 1, opts);

    // uPlotManager is non-copiable so we use a pointer
    std::map<std::string, uPlotManagerPtr> services;

    // Add services not listed in the uPlotTable
    std::vector<std::string> svcNotInTable = {"UPLOT_MANAGER", "MCOAST", "MTEXT", "MLEGEND"};
    for (const auto& cls : svcNotInTable) {
        services[cls] = std::make_shared<uPlotManager>(cls.c_str());
    }

    // Add services from the uPlotTable
    MvRequest r;
    r.read(metview::etcDirFile("uPlotTable").c_str());
    if (r) {
        do {
            const char* verb = r.getVerb();
            if (verb && (strcmp(verb, "request") == 0 || strcmp(verb, "view") == 0 ||
                         strcmp(verb, "visdef") == 0)) {
                if (const char* clsCh = r("class")) {
                    const char* mgr = r("manager");
                    if (!mgr || strcmp(mgr, "False") != 0) {
                        std::string cls(clsCh);
                        if (services.find(cls) == services.end()) {
                            services[cls] = std::make_shared<uPlotManager>(clsCh);
                        }
                    }
                }
            }
        } while (r.advance());
    }

#if 0
    int cnt=0;
    for(auto it: services) {
         std::cout << cnt << " " << it.first << std::endl;
         cnt++;
    }
#endif

    theApp.run();
}
