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

#define P_INST 0
#define P_TAVG 1
#define P_TACC 3

#define TYPE_AN 2
#define TYPE_FC 9
#define TYPE_CF 10
#define TYPE_PF 11
#define TYPE_FF 25
#define TYPE_OF 26
#define TYPE_OR 70
#define TYPE_FX 71

int grib_ocean_fix_section_1(gribsec1* s1, request* r) {
    int ierror        = 0;
    fortint mars_type = s1->local.mars_type;

    static char* iproduct[] = {
        /* 0*/ "INST",
        /* 1*/ "TAVG",
        /* 2*/ "2",
        /* 3*/ "TACC",
    };

    static char* isection[] = {
        /*  */ "0",
        /* 1*/ "1",
        /* 2*/ "H",
        /* 3*/ "M",
        /* 4*/ "Z",
    };

    static char* tsection[] = {
        /*  */ "0",
        /* 1*/ "1",
        /* 2*/ "2",
        /* 3*/ "V",
        /* 4*/ "Z",
        /* 5*/ "M",
    };

    /* gribsec1_extra *extra_s1 = grib_extra_section_1(s1); */

    /* EM, STD, CF, PB, PD do not have NUMBER */
    /* This is for old Monthly Forecast, present in MARS archive only.
       They have been superseed by new Monthly Forecast */
    if (s1->local.mars_type != 17 && s1->local.mars_type != 18 && s1->local.mars_type != 29 && s1->local.mars_type != 36 && s1->local.mars_type != 10) {
        set_value(r, "NUMBER", "%" D "", s1->local.u.ocean.mars_number);
    }

    /* This is very ugly, but I didn't know anywhere else
       where to put it */
    if (s1->local.mars_stream != GRIB_STREAM_ENFO && s1->local.mars_stream != GRIB_STREAM_ENFO_HINDCAST_OBSOLETE && s1->local.mars_stream != GRIB_STREAM_ENFH_HINDCAST && s1->local.mars_stream != GRIB_STREAM_EFHO_HINDCAST) {
        set_value(r, "METHOD", "%" D "", s1->local.u.ocean.method);

        if (s1->local.mars_class == GRIB_CLASS_OD)
            set_value(r, "SYSTEM", "%" D "", s1->local.u.ocean.system);
    }
    set_value(r, "_TOTAL_NUMBER", "0");

    if (s1->local.u.ocean.horizontal_coordinates == 0) {
        fortfloat coord1 = s1->local.u.ocean.coordinate_1_start_position;
        fortfloat coord2 = s1->local.u.ocean.coordinate_2_start_position;

        if (s1->local.u.ocean.coordinate_1_locating == 1) /* instantaneously valid fields */
        {
            if (s1->local.u.ocean.coordinate_1_averaging >= 0 && s1->local.u.ocean.coordinate_1_averaging < NUMBER(iproduct)) {
                set_value(r, "PRODUCT", "%s",
                          iproduct[s1->local.u.ocean.coordinate_1_averaging]);
            }

            /* Especial case for OR products. */
            /* The GRIB header does not fit the standards of MARS */

            /* TYPE=OR
               PRODUCT=TAVG or TACC */
            if (mars_type == TYPE_OR && (s1->local.u.ocean.coordinate_1_averaging == P_TAVG || s1->local.u.ocean.coordinate_1_averaging == P_TACC)) {
                basedate_to_verifydate(s1, r);
                if (s1->local.u.ocean.coordinate_1_averaging == P_TAVG) {
                    set_value(r, "RANGE", "%" D "",
                              (s1->local.u.ocean.coordinate_1_end_position - s1->local.u.ocean.coordinate_1_start_position) / 3600);
                }
            }
            /* TYPE=FC,CF,FF or OF   PRODUCT=TAVG or TACC */
            else if ((mars_type == TYPE_FC || mars_type == TYPE_CF || mars_type == TYPE_PF || mars_type == TYPE_FF || mars_type == TYPE_OF) && s1->local.u.ocean.coordinate_1_averaging == P_TAVG || s1->local.u.ocean.coordinate_1_averaging == P_TACC) {
                /* TYPE=FC, PRODUCT=TAVG needs RANGE */
                if ((mars_type == TYPE_FC || mars_type == TYPE_FF) && (s1->local.u.ocean.coordinate_1_averaging == P_TAVG)) {
                    set_value(r, "RANGE", "%" D "",
                              (s1->local.u.ocean.coordinate_1_end_position - s1->local.u.ocean.coordinate_1_start_position) / 3600);
                }
            }
            /* TYPE=AN/OR, PRODUCT=INST */
            else if ((mars_type == TYPE_AN || mars_type == TYPE_OR) && s1->local.u.ocean.coordinate_1_averaging == P_INST) {
            }
            /* TYPE=FC,CF,FF or OF   PRODUCT=INST */
            else if ((mars_type == TYPE_FC || mars_type == TYPE_CF || mars_type == TYPE_PF || mars_type == TYPE_FF || mars_type == TYPE_OF) && s1->local.u.ocean.coordinate_1_averaging == P_INST) {
            }
            /* TYPE=FX, PRODUCT=TAVG */
            else if (mars_type == TYPE_FX && s1->local.u.ocean.coordinate_1_averaging == P_TAVG) {
                basedate_to_verifydate(s1, r);
                set_value(r, "RANGE", "%" D "",
                          (s1->local.u.ocean.coordinate_1_end_position - s1->local.u.ocean.coordinate_1_start_position) / 3600);
            }
            else {
                ierror = 1;
                marslog(LOG_WARN, "Unknown coordinate 1 averaging value : %" D "",
                        s1->local.u.ocean.coordinate_1_averaging);
            }

            if (s1->local.u.ocean.coordinate_2_locating > 0 && s1->local.u.ocean.coordinate_2_locating < NUMBER(isection)) {
                set_value(r, "SECTION", "%s",
                          isection[s1->local.u.ocean.coordinate_2_locating]);
            }
            else {
                ierror = 1;
                marslog(LOG_WARN, "Unknown section configuration : %" D "",
                        s1->local.u.ocean.coordinate_2_locating);
            }

            switch ((int)s1->local.u.ocean.coordinate_2_locating) {
                case GRIB_DEPTH: /* 2 horizontal fields */
                    set_value(r, "LEVELIST", "%.3f", round_decimal(coord2 / 1.0e3));
                    break;
                case GRIB_LONGITUDE: /* 3 meridional fields */
                    set_value(r, "LONGITUDE", "%.3f", round_decimal(coord2 / 1.0e6));
                    /* set_value(r,"LEVELIST", "OFF"); */
                    break;
                case GRIB_LATITUDE: /* 4 longitudinal fields */
                    set_value(r, "LATITUDE", "%.3f", round_decimal(coord2 / 1.0e6));
                    /* set_value(r,"LEVELIST", "OFF"); */
                    break;
            }
        }
        else /* time series */
        {
            set_value(r, "PRODUCT", "TIMS");

            /* Especial case for OR products. */
            /* The GRIB header does not fit the standards of MARS */

            if ((mars_type == TYPE_OR || mars_type == TYPE_FC || mars_type == TYPE_CF || mars_type == TYPE_PF || mars_type == TYPE_FF || mars_type == TYPE_OF) && s1->local.u.ocean.coordinate_1_averaging == 0) {
                if (mars_type == TYPE_OR)
                    basedate_to_verifydate(s1, r);

                set_value(r, "RANGE", "%" D "", (s1->local.u.ocean.coordinate_3_end_grid_point - s1->local.u.ocean.coordinate_3_start_grid_point) / 3600);
                if (s1->local.u.ocean.coordinate_4_axis == 1) {
                    set_value(r, "RANGE", "%" D "", (s1->local.u.ocean.coordinate_4_end_grid_point - s1->local.u.ocean.coordinate_4_start_grid_point) / 3600);
                }
            }

            if (s1->local.u.ocean.coordinate_3_axis > 0 && s1->local.u.ocean.coordinate_4_axis > 0 && s1->local.u.ocean.coordinate_3_axis + s1->local.u.ocean.coordinate_4_axis < NUMBER(tsection)) {
                set_value(r, "SECTION", "%s",
                          tsection[s1->local.u.ocean.coordinate_3_axis + s1->local.u.ocean.coordinate_4_axis]);
            }
            else {
                ierror = 1;
                marslog(LOG_WARN, "Unknown ocean axis coordinates : %" D " x %" D "",
                        s1->local.u.ocean.coordinate_3_axis,
                        s1->local.u.ocean.coordinate_4_axis);
            }

            if (s1->local.u.ocean.coordinate_3_axis + s1->local.u.ocean.coordinate_4_axis == 3) {
                set_value(r, "LATITUDE", "%.3f", round_decimal(coord1 / 1.0e6));
                set_value(r, "LONGITUDE", "%.3f", round_decimal(coord2 / 1.0e6));
            }
            else if (s1->local.u.ocean.coordinate_3_axis + s1->local.u.ocean.coordinate_4_axis == 4) {
                set_value(r, "LEVELIST", "%.3f", round_decimal(coord1 / 1.0e3));
                set_value(r, "LATITUDE", "%.3f", round_decimal(coord2 / 1.0e6));
            }
            else if (s1->local.u.ocean.coordinate_3_axis + s1->local.u.ocean.coordinate_4_axis == 5) {
                set_value(r, "LEVELIST", "%.3f", round_decimal(coord1 / 1.0e3));
                set_value(r, "LONGITUDE", "%.3f", round_decimal(coord2 / 1.0e6));
            }
            else {
                ierror = 1;
                marslog(LOG_WARN, "Unknown ocean axis : %" D " x %" D "",
                        s1->local.u.ocean.coordinate_3_axis,
                        s1->local.u.ocean.coordinate_4_axis);
            }
        }
    }

    return (ierror);
}
