/***************************** 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 "MvUiService.h"
#include "MvApplication.h"
#include "MvMiscellaneous.h"
#include "MvTmpFile.h"

#include <iostream>
#include <chrono>
#include <thread>
#include <assert.h>

#define MvUiService_DEBUG__


MvUiService::MvUiService(const char* name) :
    MvService(name)
{
    // interactive modules are not caching data (always true?)
    saveToPool(false);
}

MvUiService::~MvUiService() = default;

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

    std::string mode;
    if (const char* modeCh = (const char*)in("_ACTION")) {
        mode = std::string(modeCh);
    }
    if (mode.empty()) {
        if (const char* appl = (const char*)in("_APPL")) {
            if (strcmp(appl, "macro") == 0 || strcmp(appl, "Python") == 0) {
                // this will work for wmsclient
                mode = "visualise";
            }
        }
        if (mode.empty()) {
            mode = "any";
        }
    }

    auto it = apps_.find(mode);
    if (it == apps_.end()) {
        marslog(LOG_EROR, "action=%s is not supported for request type=%s!", mode.c_str(), in.getVerb());
        setError(13);
        return;
    }

    // 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!

    // As a safety measure we only apply it to the WMSCLIENT beacuse we know it happens when
    // run in batch mode!
    if (strcmp(in.getVerb(), "WMSCLIENT") == 0) {
        MvRequest::replaceDotInPath(in);
    }

    auto appItem = it->second;
    auto appName = appItem.appName_;

    bool waitApp = false;
    if (appItem.hasOutput_) {
        waitApp = true;
    }
    else if (const char* waitAppCh = in("_WAIT_APP")) {
        if (strcmp(waitAppCh, "1") == 0) {
            waitApp = true;
        }
    }

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

    if (const char* pidFileCh = in("_PID_FILE")) {
        in("_PID_FILE") = pidFileCh;
    }

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

    // Start the application
    std::string cmd;
    cmd += "$metview_command $METVIEW_BIN/" + appName + " " +
           reqFile.path() + " $METVIEW_QT_APPLICATION_FLAGS ";

    // if we do not need to wait for it
    if (!waitApp)
        cmd += "&";

    marslog(LOG_INFO, "Start appliction with command: %s", cmd.c_str());

    system(cmd.c_str());

    if (waitApp) {
        out.read(outFile.path().c_str(), false, true);
    }
}

void MvUiService::addApp(const std::string& appName, const std::vector<std::string>& actions, bool hasOutput)
{
    for (auto a : actions) {
        apps_[a] = MvUiServiceAppItem(appName, a, hasOutput);
    }
}
