#include "mars.h"
#include "mars_client_config.h"

boolean message_is_netcdf(unsigned char *buf) {
    if(buf)
        return ( buf[0] == 137 && buf[1] == 'H' && buf[2] == 'D' && buf[3] == 'F');
    else
        return 0;
}


#ifdef HAVE_NETCDF

#include <netcdf.h>

static const char *get_type(int type) {

    switch (type) {

    case NC_BYTE:
        return "NC_BYTE";
        break;

    case NC_SHORT:
        return "NC_SHORT";
        break;

    case NC_LONG:
        return "NC_LONG";
        break;

    case NC_CHAR:
        return "NC_CHAR";
        break;

    case NC_FLOAT:
        return "NC_FLOAT";
        break;

    case NC_DOUBLE:
        return "NC_DOUBLE";
        break;

    default:
        marslog(LOG_EROR, "Unknow attribute type %d", type);
        return "Unknow";
    }
}


static boolean file_is_netcdf(const char *path)
{
    /* See https://www.unidata.ucar.edu/software/netcdf/docs/netcdf/Classic-Format-Spec.html#Classic-Format-Spec */
    FILE *f = fopen(path, "r");
    unsigned char buf[8];

    if (f == NULL) {
        marslog(LOG_EROR | LOG_PERR, "Cannot open '%s'", path);
        return false;
    }

    if (fread(buf, 1, 4, f) != 4) {
        marslog(LOG_WARN, "file_is_netcdf: Cannot read enough bytes from %s", path);
        fclose(f);
        return false;
    }

    /* http://www.hdfgroup.org/HDF5/doc/H5.format.html#FileMetaData */

    if ( buf[0] == 137 && buf[1] == 'H' && buf[2] == 'D' && buf[3] == 'F') {

        if (fread(buf + 4, 1, 4, f) != 4) {
            marslog(LOG_WARN, "file_is_netcdf: Cannot read enough bytes from %s", path);
            fclose(f);
            return false;
        }
        if ( buf[4] == '\r' && buf[5] == '\n' && buf[6] == 26 && buf[7] == '\n') {
            marslog(LOG_DBUG, "%s is a netcdf-4 (HDF)", path);
            fclose(f);
            return true;
        }

        marslog(LOG_WARN, "%s looks like HDF", path);

    }


    fclose(f);

    if ( buf[0] == 'C' && buf[1] == 'D' && buf[2] == 'F')
    {

        switch (buf[3])
        {
        case 1:
            /* Classic format */
            marslog(LOG_DBUG, "%s is a netcdf-3 (32 bits)", path);
            return true;
            break;

        case 2:
            /* Classic format */
            marslog(LOG_DBUG, "%s is a netcdf-3 (64 bits)", path);
            return true;
            break;

        default:
            marslog(LOG_EROR, "%s: invalid netcdf version (%ld)", path, (long)buf[3]);
            return false;
            break;
        }


    }

    return false;


}

boolean source_is_netcdf(const request *r)
{
    int i = 0;
    const char *path;
    boolean ok = true;

    marslog(LOG_DBUG, "Checking is source is NETCDF");

    while ((path = get_value(r, "SOURCE", i++)) != NULL)
    {
        path = no_quotes(path);
        boolean nc = file_is_netcdf(path);

        if (nc) {
            /* For now, only hdf5 */
            if (check_hdf5_superblock(path) != 0) {
                marslog(LOG_EXIT, "Open NETCDF-4 data with HDF5 Super Block version 2 supported");
            }
        }
        // marslog(LOG_DBUG, "%s is %sNetCDF", path, nc ? "": "not ");
        if (i > 1) {
            if (ok != nc) {
                marslog(LOG_EXIT, "Cannot support a mix of netcdf/non-netcdf files");
            }
        }
        else {
            ok = nc;
        }
    }

    if (ok)
        marslog(LOG_DBUG, "Source is NETCDF");
    else
        marslog(LOG_DBUG, "Source is not NETCDF");

    return ok;
}


request* netcdf_to_request(const char *path, int merge, mars_field_index *idx, err* e) {
    err ret = 0;
    request *r;

    netcdf_schema *s = netcdf_schema_new(path);
    r = netcdf_schema_to_request(s, merge, idx, e);
    netcdf_schema_delete(s);

    return r;
}


#else

static const char *get_type(int type) {
    marslog(LOG_EROR, "Attempt to get_type() NETCDF, NETCDF support not enabled");
    return 0;
}

static boolean file_is_netcdf(const char *path)
{
    marslog(LOG_EROR, "Attempt to access NETCDF file %s, NETCDF support not enabled", path);
    return -2;
}

boolean source_is_netcdf(const request *r) {
    const char *path = get_value(r, "SOURCE", 0);
    marslog(LOG_EROR, "Attempt to access NETCDF file %s, NETCDF support not enabled", path);
    return false;
}

request* netcdf_to_request(const char *path, int merge, mars_field_index *idx, err* e)
{
    marslog(LOG_EROR, "Attempt to access NETCDF file %s, NETCDF support not enabled", path);
    return -2;
}

#endif
