/*
 * © 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"


#include <iostream>

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


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;
    pproc->print_version();
    return NOERR;
}

} // extern "C"
