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

 Copyright 2020 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 "MvRequest.h"
#include "MvProtocol.h"
#include "MvApplication.h"
#include "MvService.h"
#include "MvMiscellaneous.h"
#include "MvTmpFile.h"

#include <sys/wait.h>

class uPlotBatchService : public MvService
{
public:
    uPlotBatchService(const char* name) :
        MvService(name) {}
    virtual ~uPlotBatchService() = default;

    uPlotBatchService(const uPlotBatchService&) = delete;
    ;
    uPlotBatchService& operator=(const uPlotBatchService&) = delete;

    void serve(MvRequest&, MvRequest&) override;
};

void uPlotBatchService::serve(MvRequest& in, MvRequest& out)
{
    marslog(LOG_INFO, "serve");
    in.print();

    // the output request will be written into this file
    MvTmpFile outFile(false);
    in("_OUT_REQ_FILE") = outFile.path().c_str();

    //When the request written into a file and contains a "." value we cannot
    //read it because the request parser fails reporting a syntax error!
    //So we need to make sure the request does not contain any "." values!

    //TODO: the solution below in not generic and only fixes the _PATH = .
    //case. On top of that "." in theory could be a valid value in a request!
    MvRequest::replaceDotInPath(in);

    // Write the in request into a file
    MvTmpFile reqFile(false);
    in.save(reqFile.path().c_str(), true);

    // for debugging we can save the in request into a location
    // defined by an env var
    if (const char* ch = getenv("MV_UPLOTBATCH_DEBUG_REQ_PATH")) {
        in.save(ch, true);
    }

    // Start the application in a blocking mode
    std::string cmd;
    cmd += "$METVIEW_BIN/uPlotBatchApp " + reqFile.path();
    marslog(LOG_INFO, "Start appliction with command: %s", cmd.c_str());
    int ret = system(cmd.c_str());

    marslog(LOG_INFO, "ret=%d", ret);

    if (ret != 0) {
        out             = MvRequest("ERROR");
        std::string msg = "uPlotBatch run failed with exit code: " + std::to_string(ret);
        // we do not use LOG_EROR here because in this case the error
        // message would appear twice in he macro editor console
        marslog(LOG_INFO, msg.c_str());
        out("MESSAGE") = msg.c_str();
    }

    // Read output
    MvRequest out_r;
    out_r.read(outFile.path().c_str(), false, true);

    // if there was an ERROR request generated we replace out with it.
    // Otherwise there could be 2 ERROR requests in out: this one and
    // the one coming from the system return value above. However, the
    // macro editor would only report the first one. So we just keep the
    // (probably) more significant error message.
    const char* outVerb = out_r.getVerb();
    if (outVerb && strcmp(outVerb, "ERROR") == 0) {
        out = out_r;
    }
    else {
        out = out + out_r;
    }

    marslog(LOG_INFO, "out request:");
    out.print();
}

int main(int argc, char** argv)
{
    MvApplication app(argc, argv);
    uPlotBatchService req1("PRINTER_MANAGER");

    app.run();
}
