#include <stdio.h>
#include <stdlib.h>

#include "test.h"
#include "fes.h"

#ifdef WIN32
#define INI                 "../../test/fes.ini"
#define FES_DATA            "FES_DATA=../../data"
#else
#define INI                 "fes.ini"
#define FES_DATA            "../data"
#endif

#define CHECK_TIDE(a, b, c)    fabs((a)-(b)) > c

static int total_err = 0;

int test(fes_enum_access access)
{
    int err;
    int hour;
    int	isData;
    double lon = -7.688;
    double lat = 59.195;
    double tide;
    double time, time_got;
    double lp;
    double load;
    double loadlp;
    FES short_tide;
    FES radial_tide;

    printf("*** testing libfes with %s...\n",
            access == FES_IO ? "direct access" : "memory access");

    if (fes_new(&short_tide, FES_TIDE, access, INI))
    {
        printf("fes error : %s\n", fes_error(short_tide));
        goto on_error;
    }

    if (fes_new(&radial_tide, FES_RADIAL, access, INI))
    {
        printf("fes error : %s\n", fes_error(radial_tide));
        goto on_error;
    }

    for (hour = 0, time = 12053; hour < 24; hour++, time += 1 / 24.0)
    {
        /* Compute tide */
        if (fes_core(short_tide, lat, lon, time, &tide, &lp))
        {
            if (fes_errno(short_tide) == FES_NO_DATA)
                continue;
            else
            {
                fprintf(stderr, "%s\n", fes_error(short_tide));
                goto on_error;
            }
        }

        if (fes_core(radial_tide, lat, lon, time, &load, &loadlp))
        {
            if (fes_errno(radial_tide) == FES_NO_DATA)
                continue;
            else
            {
                fprintf(stderr, "%s\n", fes_error(radial_tide));
                goto on_error;
            }
        }

        switch (hour)
        {
        case 0:
            err = CHECK_TIDE(tide, -94.15935039, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(lp, 0.87568897, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(load, 3.91448325, 1E-5);
            SUMMARIZE_ERR;
            break;
        case 1:
            err = CHECK_TIDE(tide, -133.79643203, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(lp, 0.84647835, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(load, 4.38651343, 1E-5);
            SUMMARIZE_ERR;
            break;
        case 2:
            err = CHECK_TIDE(tide, -139.13795757, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(lp, 0.81660979, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(load, 3.77976793, 1E-5);
            SUMMARIZE_ERR;
            break;
        case 3:
            err = CHECK_TIDE(tide, -107.83359184, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(lp, 0.78610219, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(load, 2.19755107, 1E-5);
            SUMMARIZE_ERR;
            break;
        case 4:
            err = CHECK_TIDE(tide, -48.26358367, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(lp, 0.75497485, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(load, -0.00976397, 1E-5);
            SUMMARIZE_ERR;
            break;
        case 5:
            err = CHECK_TIDE(tide, 24.77529608, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(lp, 0.72324750, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(load, -2.33012719, 1E-5);
            SUMMARIZE_ERR;
            break;
        case 6:
            err = CHECK_TIDE(tide, 94.77575203, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(lp, 0.69094025, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(load, -4.21626261, 1E-5);
            SUMMARIZE_ERR;
            break;
        case 7:
            err = CHECK_TIDE(tide, 144.80648776, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(lp, 0.65807358, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(load, -5.22134915, 1E-5);
            SUMMARIZE_ERR;
            break;
        case 8:
            err = CHECK_TIDE(tide, 160.67935252, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(lp, 0.62466835, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(load, -5.10976963, 1E-5);
            SUMMARIZE_ERR;
            break;
        case 9:
            err = CHECK_TIDE(tide, 137.67986824, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(lp, 0.59074573, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(load, -3.91507924, 1E-5);
            SUMMARIZE_ERR;
            break;
        case 10:
            err = CHECK_TIDE(tide, 82.80750261, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(lp, 0.55632722, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(load, -1.93069697, 1E-5);
            SUMMARIZE_ERR;
            break;
        case 11:
            err = CHECK_TIDE(tide, 10.15904197, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(lp, 0.52143464, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(load, 0.36417963, 1E-5);
            SUMMARIZE_ERR;
            break;
        case 12:
            err = CHECK_TIDE(tide, -63.69060656, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(lp, 0.48609010, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(load, 2.42460343, 1E-5);
            SUMMARIZE_ERR;
            break;
        case 13:
            err = CHECK_TIDE(tide, -121.72848139, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(lp, 0.45031596, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(load, 3.77548578, 1E-5);
            SUMMARIZE_ERR;
            break;
        case 14:
            err = CHECK_TIDE(tide, -149.42514287, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(lp, 0.41413484, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(load, 4.12859563, 1E-5);
            SUMMARIZE_ERR;
            break;
        case 15:
            err = CHECK_TIDE(tide, -139.73843276, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(lp, 0.37756962, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(load, 3.45159430, 1E-5);
            SUMMARIZE_ERR;
            break;
        case 16:
            err = CHECK_TIDE(tide, -96.57911288, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(lp, 0.34064336, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(load, 1.97199202, 1E-5);
            SUMMARIZE_ERR;
            break;
        case 17:
            err = CHECK_TIDE(tide, -32.56173103, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(lp, 0.30337936, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(load, 0.11543738, 1E-5);
            SUMMARIZE_ERR;
            break;
        case 18:
            err = CHECK_TIDE(tide, 36.50917127, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(lp, 0.26580106, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(load, -1.60563661, 1E-5);
            SUMMARIZE_ERR;
            break;
        case 19:
            err = CHECK_TIDE(tide, 94.17382530, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(lp, 0.22793209, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(load, -2.72449641, 1E-5);
            SUMMARIZE_ERR;
            break;
        case 20:
            err = CHECK_TIDE(tide, 124.81848317, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(lp, 0.18979623, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(load, -2.93998756, 1E-5);
            SUMMARIZE_ERR;
            break;
        case 21:
            err = CHECK_TIDE(tide, 119.45370604, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(lp, 0.15141735, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(load, -2.19341957, 1E-5);
            SUMMARIZE_ERR;
            break;
        case 22:
            err = CHECK_TIDE(tide, 80.72425404, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(lp, 0.11281948, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(load, -0.68309456, 1E-5);
            SUMMARIZE_ERR;
            break;
        case 23:
            err = CHECK_TIDE(tide, 20.45691253, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(lp, 0.07402669, 1E-5);
            SUMMARIZE_ERR;
            err = CHECK_TIDE(load, 1.18699356, 1E-5);
            SUMMARIZE_ERR;
            break;
        default:
            abort();
        }
    }

    fes_delete(short_tide);
    fes_delete(radial_tide);

    return 0;

    on_error: return 1;
}

/*
 */
int main(void)
{
    int total_err = 0, err;

#ifdef WIN32
    _putenv(FES_DATA);
#else
    setenv("FES_DATA", FES_DATA, 1);
#endif

    err = test(FES_IO);
    SUMMARIZE_ERR;

    //err = test(FES_MEM);
    //SUMMARIZE_ERR;

    FINAL_RESULTS;
}
