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

static char* scan_file(const char* file) {
    FILE* f = fopen(file, "r");
    int len;
    int max;
    unsigned char c = ' ';

    union {
        char c;
        short s;
        long l;
        char ch[8];
    } buf;

    if (f == NULL)
        return "BAD";

    memset(&buf, 0, sizeof(buf));


    if ((len = fread((char*)&buf, 1, sizeof(buf), f)) < 0) {
        fclose(f);
        marslog(LOG_DBUG, "Bad len '%d' while reading '%s'", len, file);
        return "BAD";
    }

    if (strncmp(buf.ch, "%!", 2) == 0) {
        fclose(f);
        return "PSFILE";
    }

    if (strncmp(buf.ch, "#!", 2) == 0) {
        fclose(f);
        return "SHELL";
    }

    if (strncmp(buf.ch, "GRIB", 4) == 0) {
        fclose(f);
        return "GRIB";
    }

    if (strncmp(buf.ch, "TIDE", 4) == 0) {
        fclose(f);
        return "GRIB";
    }

    if (strncmp(buf.ch, "BUDG", 4) == 0) {
        fclose(f);
        return "GRIB";
    }

    if (strncmp(buf.ch, "BUFR", 4) == 0) {
        fclose(f);
        return "BUFR";
    }

    if (strncmp(buf.ch, "%!", 2) == 0) {
        fclose(f);
        return "POSTSCRIPT";
    }

    if (strncmp(buf.ch, "#GEO", 4) == 0) {
        fclose(f);
        return "GEOPOINTS";
    }

    if (strncmp(buf.ch, "#LLM", 4) == 0) {
        fclose(f);
        return "LLMATRIX";
    }

    if (strncmp(buf.ch + 2, "GRIB", 4) == 0) {
        fclose(f);
        return "GRIB";
    }

    if (strncmp(buf.ch + 4, "GRIB", 4) == 0) {
        fclose(f);
        return "GRIB";
    }

    if (strncmp(buf.ch + 2, "BUFR", 4) == 0) {
        fclose(f);
        return "BUFR";
    }

    if (strncmp(buf.ch + 4, "BUFR", 4) == 0) {
        fclose(f);
        return "BUFR";
    }

    if (strncmp(buf.ch, "CDF", 3) == 0) {
        fclose(f);
        return "NETCDF";
    }

    rewind(f);

    max = 4096; /* 4 K */
    while (max-- > 0 && !feof(f)) {
        fread((char*)&c, 1, 1, f);
        if (!isprint(c) && !isspace(c)) {
            fclose(f);
            return "BINARY";
        }
    }

    fclose(f);
    return "NOTE";
}

char* guess_class(const char* file) {

    struct stat buf;

    if (stat(file, &buf) < 0)
        return "BAD";

    switch (buf.st_mode & S_IFMT) {
        case S_IFDIR:
            return "FOLDER";

        case S_IFREG:
            return scan_file(file);

        default:
            return "SPECIAL";
    }
}
