/***************************** 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 "mars_client_config.h"
#include <Metview.h>
#include <stdarg.h>

svc* MvApplication::Service           = NULL;
MvApplication* MvApplication::app     = 0;
int KeepAlive::count_                 = 0;
boolean MvApplication::ProcessReplies = 0;
static const char* cPreferencesFile   = "General";

MvApplication::MvApplication(int& argc, char** argv, const char* name, void* aparg, int nopt, option* opt)
{
    app = this;

    marsinit(&argc, argv, aparg, nopt, opt);
    Service = create_service(name ? name : progname());
    MvServiceFactory::installServices();
}

boolean MvApplication::stopAll(const char* fmt, ...)
{
    char* p = getenv("METVIEW_MODE");

    if (!p)
        return false;

    if (strcmp(p, "batch") != 0)
        return false;

    va_list list;
    char buf[1024];

    va_start(list, fmt);
    vsprintf(buf, fmt, list);
    va_end(list);

    stop_all(Service, buf, 1);

    return true;
}

void MvApplication::setKeepAlive(boolean on)
{
    keep_alive(Service, on ? 1 : 0);
}

void MvApplication::setMaximum(int n)
{
    set_maximum(Service, n);
}

void MvApplication::setExitTimeout(int minutes)
{
    exit_timeout(Service, minutes);
}

void MvApplication::run()
{
    /* if (!mars.nofork) setExitTimeout(1); // 1 minute */
    service_run(Service);
}

void MvApplication::callService(const char* s, const MvRequest& r, void* d)
{
    /*
	if(ProcessReplies)
		while(service_ready(Service))
		{
			marslog(LOG_DBUG,"Processing async replies...");
			process_service(Service);
		}
*/
    call_service(Service, s, r, (long)d);
}

MvRequest MvApplication::waitService(const char* s, const MvRequest& r, int& err)
{
    err = 0;
    return MvRequest(wait_service(Service, (char*)s, r, &err), false);
}

void MvApplication::callFunction(const char* s, const MvRequest& r, void* d)
{
    call_function(Service, s, r, (long)d);
}

void MvApplication::sendMessage(const MvRequest& r)
{
    send_message(Service, r);
}

void MvApplication::recordOn(boolean on)
{
    recording(Service, on);
}

void MvApplication::setFork(boolean on)
{
    mars.nofork = !on;
}

void MvApplication::notifyIconCreation(const char* icon_name, const char* icon_class)
{
    request* u = empty_request("STATUS");
    set_value(u, "NAME", "%s", icon_name);
    set_value(u, "CLASS", "%s", icon_class);
    set_value(u, "STATUS", "CREATED");
    send_message(Service, u);
    free_all_requests(u);
}

void MvApplication::notifyIconModified(const char* icon_name, const char* icon_class)
{
    request* u = empty_request("STATUS");
    set_value(u, "NAME", "%s", icon_name);
    set_value(u, "CLASS", "%s", icon_class);
    set_value(u, "STATUS", "MODIFIED");
    send_message(Service, u);
    free_all_requests(u);
}

MvRequest MvApplication::getPreferences(const char* name)
{
    const char* prefs_name = (name == NULL) ? cPreferencesFile : name;
    char buf[1024];
    sprintf(buf, "%s/System/Preferences/%s",
            getenv("METVIEW_USER_DIRECTORY"), prefs_name);

    return read_request_file(buf);
}

MvRequest MvApplication::getExpandedPreferences(const char* name)
{
    const char* prefs_name = (name == NULL) ? cPreferencesFile : name;
    //MvRequest req=get_preferences(Service,prefs_name);
    MvRequest req = getPreferences(prefs_name);

    char* shareDir = getenv("METVIEW_DIR_SHARE");
    if (!shareDir)
        return req;

    string path(shareDir);
    path.append("/etc/");

    string defFileName   = path + "ConfigDef";
    string rulesFileName = path + "ConfigRules";

    MvLanguage langMetview(defFileName.c_str(),
                           rulesFileName.c_str(),
                           EXPAND_DEFAULTS);

    return langMetview.expandOne(req);
}

void MvApplication::setPreferences(const MvRequest& req, const char* name)
{
    const char* prefs_name = (name == NULL) ? cPreferencesFile : name;
    char buf[1024];
    sprintf(buf, "%s/System/Preferences/%s",
            getenv("METVIEW_USER_DIRECTORY"), prefs_name);

    req.save(buf);
}

//! (used by MvApplication)
/*! This class is used by method MvApplication::wantPreferences().
 */
class MvPreferenceMessage : public MvMessage
{
    MvApplication* appl;

public:
    MvPreferenceMessage(const char* name, MvApplication* a) :
        MvMessage(name),
        appl(a) {}
    virtual void callback(MvRequest& r) { appl->newPreferences(r); }
};

void MvApplication::wantPreferences(const char* name)
{
    new MvPreferenceMessage(name ? name : "GENERAL_PREFERENCES", this);
}

void MvApplication::addInputCallback(FILE* f, inputproc p, void* data)
{
    add_input_callback(Service, f, p, data);
}


MvRequest MvApplication::poolFetch(const char* icon_name, const char* icon_class)
{
    return pool_fetch(Service, icon_name, icon_class);
}
void MvApplication::poolStore(const char* icon_name, const char* icon_class,
                              const MvRequest& r)
{
    pool_store(Service, icon_name, icon_class, r);
}

void MvApplication::poolLink(const char* name1, const char* name2)
{
    pool_link(Service, name1, name2);
}
