/*
 * © Copyright 1996-2012 ECMWF.
 *
 * This software is licensed under the terms of the Apache Licence Version 2.0
 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
 * In applying this licence, ECMWF does not waive the privileges and immunities
 * granted to it by virtue of its status as an intergovernmental organisation nor
 * does it submit to any jurisdiction.
 */

#include "pproc.h"
#include "mars_client_config.h"


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


namespace marsclient {

PProc::PProc() {
}

PProc::~PProc() {
}


PProcFactory& PProcFactory::instance() {
    static PProcFactory f;
    return f;
}

void PProcFactory::insert(const std::string& name, PProcBuilder* b) {
    m_[name] = b;
}

PProc* PProcFactory::build(const std::string& name) const {

    std::map<std::string, PProcBuilder*>::const_iterator f = m_.find(name);

    if (f != m_.end()) {

        if (f->second != NULL)
            return f->second->build();

        marslog(LOG_EROR, "Error in PProc factory trying to build backend %s", name.c_str());
        return 0;
    }
    else {
        return 0;
    }
}


PProcFactory::PProcFactory() {
}


}  // namespace marsclient


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

static marsclient::PProc* pproc = NULL;

extern "C" {

bool valid_pproc() {
    if (!pproc)
        marslog(LOG_EROR, "Access to PProc before initialisation");
    return pproc;
}

err ppinit(const request* r, postproc* proc) {
    if (!valid_pproc())
        return POSTPROC_ERROR;
    marslog(LOG_DBUG, "Forwarding ppinit()");
    return pproc->ppinit(r, proc);
}

err ppdone(void) {
    if (!valid_pproc())
        return POSTPROC_ERROR;
    return pproc->ppdone();
}

err ppcount(int* in, int* out) {
    if (!valid_pproc())
        return POSTPROC_ERROR;
    return pproc->ppcount(in, out);
}

err pparea(request* r) {
    if (!valid_pproc())
        return POSTPROC_ERROR;
    return pproc->pparea(r);
}

fieldset* pp_fieldset(const char* file, request* filter) {
    if (!valid_pproc())
        return NULL;
    return pproc->pp_fieldset(file, filter);
}

err ppstyle(const request* r) {
    if (!valid_pproc())
        return POSTPROC_ERROR;
    return pproc->ppstyle(r);
}

err pprotation(const request* r) {
    if (!valid_pproc())
        return POSTPROC_ERROR;
    return pproc->pprotation(r);
}

long ppestimate() {
    if (!valid_pproc())
        return POSTPROC_ERROR;
    return pproc->ppestimate();
}

err makeuv(char* vo, char* d, long inlen, char* u, char* v, long* outlen) {
    if (!valid_pproc())
        return POSTPROC_ERROR;
    return pproc->makeuv(vo, d, inlen, u, v, outlen);
}

const char* pproc_name() {

    const char* pprocname = ::getenv("MARS_PPROC_BACKEND");

// default pproc
#if mars_client_HAVE_PPROC_EMOS
    if (!pprocname) {
        pprocname = "EMOS";
    }
#elif mars_client_HAVE_PPROC_MIR
    if (!pprocname) {
        pprocname = "MIR";
    }
#else
    if (!pprocname) {
        pprocname = "None";
    }
#endif

    return pprocname;
}


int pproc_initialise(int argc, char** argv) {

    const char* pprocname = pproc_name();

    pproc = marsclient::PProcFactory::instance().build(pprocname);

    if (!pproc) {
        marslog(LOG_EROR, "Could not create PPROC backend %s", pprocname);
        return -1;
    }

    marslog(LOG_DBUG, "Created PPROC backend %s", pproc->name().c_str());

    return pproc->initialise(argc, argv);
}

err pproc_print_version() {
    if (!valid_pproc())
        return POSTPROC_ERROR;

    marslog(LOG_DBUG, "Post-processing backend is %s", pproc_name());
    pproc->print_version();

    return NOERR;
}

}  // extern "C"
