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

#ifndef CRAY
#define PBGRIB pbgrib_
#endif

typedef struct gribdata {

    boolean obs;
    char* gname;
    char* bname;
    FILE* f;

} gribdata;

static void grib_init(void);
static err grib_open(void* data, request*, request*, int);
static err grib_close(void* data);
static err grib_read(void* data, request* r, void* buffer, long* length);
static err grib_write(void* data, request* r, void* buffer, long* length);


static option opts[] = {
    {"grib", NULL, "-grib", NULL, t_str, sizeof(char*), OFFSET(gribdata, gname)},
    {"bufr", NULL, "-bufr", NULL, t_str, sizeof(char*), OFFSET(gribdata, bname)},
};

static base_class _gribbase = {

    NULL,       /* parent class */
    "gribbase", /* name         */

    false, /* inited       */

    sizeof(gribdata), /* private size */
    NUMBER(opts),     /* option count */
    opts,             /* options      */


    grib_init, /* init         */

    grib_open,  /* open         */
    grib_close, /* close        */

    grib_read,  /* read         */
    grib_write, /* write        */

};

/* the only 'public' variable ... */

base_class* gribbase = &_gribbase;


static void grib_init(void) {
}

static err grib_open(void* data, request* r, request* e, int mode) {
    gribdata* g = (gribdata*)data;


    if (g->gname == NULL && r != NULL)
        g->gname = strcache(no_quotes(get_value(r, "SOURCE", 0)));

    if (g->gname != NULL) {
        marslog(LOG_DBUG, "Trying to open GRIB %s", g->gname);

        g->f   = fopen(g->gname, mode == WRITE_MODE ? "w" : "r");
        g->obs = false;
        marslog(LOG_DBUG | LOG_PERR, "File is %x", g->f);
    }
    if (!g->f && g->bname) {
        marslog(LOG_DBUG, "Trying to open BUFR %s", g->bname);
        g->f   = fopen(g->bname, mode == WRITE_MODE ? "w" : "r");
        g->obs = true;
    }

    if (g->f == NULL)
        marslog(LOG_EROR | LOG_PERR, "cannot open %s", g->gname ? g->gname : g->bname);

    return g->f == NULL ? -1 : 0;
}

static err grib_close(void* data) {
    gribdata* g = (gribdata*)data;
    if (g->f)
        fclose(g->f);
    strfree(g->gname);
    return 0;
}

static err grib_read(void* data, request* r, void* buffer, long* length) {
    gribdata* g = (gribdata*)data;
    err ret;

    if (g->obs)
        ret = _readbufr(g->f, buffer, length);
    else
        ret = _readany(g->f, buffer, length);

    if (ret != 0 && ret != -3)
        *length = 0;

    if (ret == 0 && r) {
        if (g->obs) {
            bufr_to_request(r, buffer, *length);
        }
        else {
            grib_to_request(r, buffer, *length);
        }
    }
    return ret;
}

static err grib_write(void* data, request* r, void* buffer, long* length) {
    marslog(LOG_WARN, "now in grib_write. Sorry not implemeted");
    return EOF;
}
