/*
 * © 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 <errno.h>
#include "mars.h"

err write_fieldset(fieldset* v, database* b) {
    int i;
    err e = NOERR;

    for (i = 0; i < v->count; i++) {

        long length;

        if (v->fields[i] != NULL) {
            field* g = get_field(v, i, packed_mem);

            if (g == NULL)
                return -1;

            if (g != NULL) {
                const void* buffer = field_message(g, &length);
                if (!buffer)
                    return -1;

                if ((e = database_write(b, NULL, (char*)buffer, &length)))
                    return e;

                release_field(g);
            }
        }
    }
    return NOERR;
}

err handle_read(request* r, void* data) {
    const char* s = get_value(r, "FIELDSET", 0);
    const char* f = no_quotes(get_value(r, "SOURCE", 0));
    const char* c = no_quotes(get_value(r, "CFSPATH", 0));
    fieldset* v;
    boolean pp = false;

    if (c && f) {
        marslog(LOG_WARN, "Cannot have CFSPATH and SOURCE together");
        marslog(LOG_WARN, "Ignoring CFSPATH");
        c = NULL;
    }

    if (f && ((strncmp(f, "ec:", 3) == 0) || (strncmp(f, "ectmp:", 6) == 0))) {
        char buf[1024];
        const char* tmp = marstmp();

        unlink(tmp);
        sprintf(buf, "$ECFS_SYS_PATH/ecp.p %s %s", f, tmp);


        marslog(LOG_INFO, "getting %s from ECFS", f);
        errno = 0;
        if (system(buf)) {
            marslog(LOG_EROR | LOG_PERR, "Fail to execute ", buf);
            return -2;
        }
        else
            f = tmp;
    }

    if (c) {
        char buf[1024];
        f = marstmp();

        unlink(f);
        sprintf(buf, "ecfile -p %s get %s", c, f);


        marslog(LOG_INFO, "getting %s with ecfile", c);
        errno = 0;
        if (system(buf)) {
            marslog(LOG_EROR | LOG_PERR, "Fail to execute ecfile");
            marslog(LOG_EROR, "Have you used cfslogin ?");
            return -2;
        }
    }

    pp = ((count_values(r, "GRID") != 0) || (count_values(r, "AREA") == 4) || (count_values(r, "RESOL") != 0) || (count_values(r, "ROTATION") == 2) || (mars.accuracy > 0));

    if (pp) {
        marslog(LOG_INFO, "GRIB conversion needed...");
        v = pp_fieldset(f, r);
    }
    else
        v = read_fieldset(f, r);

    if (!v)
        return -2;

    new_variable(s, v, 0);

    marslog(LOG_INFO, "%d field(s) read from file %s into '%s'",
            v->count, c ? c : f, s);

    if (count_values(r, "TARGET")) {
        request* s = empty_request("WRITE");
        err e;

        reqcpy(s, r);
        e = handle_write(s, data);

        free_all_requests(s);
        return e;
    }

    return NOERR;
}

err handle_write(request* r, void* data) {
    const char* s = get_value(r, "FIELDSET", 0);
    extern base_class* targetbase;
    err e;
    variable* v = find_variable(s);
    database* target;

    if (!v) {
        marslog(LOG_EROR, "Fieldset not found: '%s'", s);
        return -1;
    }

    if (v->scalar) {
        marslog(LOG_EROR, "WRITE failed. Field '%s' is a scalar (%g)",
                s, v->val);
        return -1;
    }

    target = database_open(targetbase, NULL, r, NULL, WRITE_MODE);

    if (target == NULL)
        return -1;

    e = write_fieldset(v->fs, target);

    database_close(target);

    if (e)
        return e;

    marslog(LOG_INFO, "WRITE %d field(s) from '%s' to file %s",
            v->fs->count, s, get_value(r, "TARGET", 0));
    return NOERR;
}
