/*
 * Copyright 2005-2018 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 "grib_api.h"

static void usage(const char *prog)
{
    fprintf(stderr,"%s:  in1 [in2 ... ]  out\n",prog);
    exit(1);
}

int main(int argc, char *argv[])
{
    int i,j;
    FILE *in;
    int e;
    grib_handle *h;
    double* values = NULL;
    size_t size;
    size_t last_size = 0;
    double min,max;
    long count = 10;
    long intervals[10];
    const char *names[1024];
    int name_count = 0;

    if(argc < 2) usage(argv[0]);

    for(i = 1; i < argc; i++)
    {
        if(argv[i][0] == '-') {
            names[name_count++] = argv[i]+1;
            continue;
        }

        in = fopen(argv[i],"r");
        if(!in) {
            perror(argv[i]);
            exit(1);
        }

        while( (h = grib_handle_new_from_file(NULL,in,&e)) != NULL )
        {
            long missingValuesPresent;
            double delta;
            GRIB_CHECK(grib_get_long(h,"missingValuesPresent",&missingValuesPresent),argv[i]);

            GRIB_CHECK(grib_get_size(h,"values",&size),argv[i]);

            if(size > last_size)
            {
                if(values) free(values);
                values = (double*)malloc(size*sizeof(double));
                last_size = size;
                if (!values) {
                    fprintf(stderr, "Failed to allocate memory for values (%lu bytes)\n", size*sizeof(double));
                    exit(1);
                }
            }

            GRIB_CHECK(grib_get_double_array(h,"values",values,&size),argv[i]);

            for(j = 0; j < count; j++)
                intervals[j] = 0;

            if(missingValuesPresent)
            {
                double missing;
                GRIB_CHECK(grib_get_double(h,"missingValue",&missing),argv[i]);

                min = max = missing;

                for(j = 0; j < size ; j++)
                {
                    if((min == missing) || ((values[j] != missing) && (min>values[j]))) min = values[j];
                    if((max == missing) || ((values[j] != missing) && (max<values[j]))) max = values[j];
                }

                delta = max- min; if(delta == 0) delta = 1;

                for(j = 0; j < size; j++)
                {
                    if(values[j] != missing)
                    {
                        int x = (values[j] - min)/delta * count;
                        if(x==count) x=x-1; /*handle the absolute  maximum*/
                        intervals[x]++;
                    }
                }
            }
            else
            {
                min = max = values[0];
                for(j = 1; j < size ; j++)
                {
                    if(min>values[j]) min = values[j];
                    if(max<values[j]) max = values[j];
                }

                delta = max- min; if(delta == 0) delta = 1;

                for(j = 0; j < size; j++)
                {
                    int x = (values[j] - min)/delta * count;
                    if(x==count) x=x-1; /*handle the absolute  maximum*/
                    intervals[x]++;
                }
            }

            for(j = 0; j < name_count; j++)
            {
                char v[1024]; size_t s = sizeof(v);
                GRIB_CHECK(grib_get_string(h,names[j],v,&s),names[j]);
                printf(" %s",v);
            }

            printf("\nmin=%g max=%g size=%ld\n",min,max,(long)size);
            for(j = 0; j < count; j++)
                printf(" %g:%g",
                        j*(max-min)/count + min
                        ,
                        (j+1)*(max-min)/count + min
                );
            printf("\n");

            for(j = 0; j < count; j++)
                printf(" %ld",intervals[j] );
            printf("\n");
        }

        GRIB_CHECK(e,argv[i]);
        fclose(in);
    }

    return 0;
}
