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

typedef struct data {
    char* file;
    int one;
    int expect;
} data;

static data setup;

static option opts[] = {
    {
        NULL,
        "GRIBTOREQUEST_FILE",
        "-f",
        NULL,
        t_str,
        sizeof(char*),
        OFFSET(data, file),
    },
    {
        NULL,
        "GRIBTOREQUEST_ONE",
        "-1",
        "0",
        t_boolean,
        sizeof(boolean),
        OFFSET(data, one),
    },
    {
        NULL,
        "GRIBTOREQUEST_EXPECT",
        "-e",
        "0",
        t_boolean,
        sizeof(boolean),
        OFFSET(data, expect),
    },
};

int main(int argc, char** argv) {
    FILE* fd     = 0;
    int e        = 0;
    int cnt      = 0;
    long buflen  = 0;
    long length  = 0;
    char* buffer = NULL;
    request* a   = empty_request("GRIB");
    char buf[80];

    marsinit(&argc, argv, &setup, NUMBER(opts), opts);
    if (!setup.file) {
        printf("Usage: %s -1 -f <file>\n", argv[0]);
        printf("          -1 : print a single request\n");
        printf("          -f : file to process\n");
        marsexit(1);
    }

    buflen = mars.readany_buffer_size;
    length = buflen;
    buffer = reserve_mem(length);

    start_timer();
    if ((fd = fopen(setup.file, "r")) == NULL) {
        marslog(LOG_EROR | LOG_PERR, "fopen: %s", setup.file);
        marsexit(1);
    }

    if (mars.readdisk_buffer > 0) {
        if (mars.readdisk_buffer > buflen)
            marslog(LOG_WARN, "Cannot use %d bytes for setvbuf, maximum size is %ld", mars.readdisk_buffer, buflen);
        else {
            marslog(LOG_DBUG, "Setting I/O read buffer to %d bytes", mars.readdisk_buffer);
            if (setvbuf(fd, buffer, _IOFBF, mars.readdisk_buffer))
                marslog(LOG_WARN | LOG_PERR, "setvbuf failed");
        }
    }

    while ((e = _readany(fd, buffer, &length)) == NOERR) {
        request* g = empty_request("GRIB");
        cnt++;
        grib_to_request(g, buffer, length);
        reqmerge(a, g);
        if (!setup.one) {
            marslog(LOG_INFO, "GRIB number %d", cnt);
            print_all_requests(g);
        }
        free_all_requests(g);
        length = buflen;
    }

    switch (e) {
        case EOF:
            e = NOERR;
        case NOERR:
            if (setup.expect)
                set_value(a, "EXPECT", "%d", cnt);
            if (setup.one)
                print_all_requests(a);
            marslog(LOG_INFO, "Decoded %d GRIB messages", cnt);
            break;
        case BUF_TO_SMALL:
            marslog(LOG_WARN, "Buffer is too small (%d bytes, %d needed.)", buflen, length);
            break;
        case NOT_FOUND_7777:
            marslog(LOG_EROR, "Group 7777 not found at the end of GRIB message");
            break;
        default:
            marslog(LOG_EROR, "readany: got unknown error %d", e);
            break;
    }

    if (buffer)
        release_mem(buffer);
    free_all_requests(a);

    stop_timer(buf);
    timer_cpu();
    if (*buf)
        marslog(LOG_INFO, "Request time: %s", buf);

    print_memory_usage(NULL);
    marsexit(e);
}
