#include "util/exception.hpp"
#include "util/geojson_validation.hpp"

#include <boost/test/unit_test.hpp>

BOOST_AUTO_TEST_SUITE(geojson_validation)

using namespace osrm;

BOOST_AUTO_TEST_CASE(timezone_coordinate_validation_test)
{
    rapidjson::Document doc;
    char valid_coord[] = "[8.28369,48.88277]";
    doc.Parse(valid_coord);
    BOOST_CHECK_NO_THROW(util::validateCoordinate(doc));

    char non_array[] = "{\"x\": 48.88277}";
    doc.Parse(non_array);
    BOOST_CHECK_THROW(util::validateCoordinate(doc), util::exception);

    char too_many[] = "[8.28369, 48.88277, 8.2806]";
    doc.Parse(too_many);
    BOOST_CHECK_THROW(util::validateCoordinate(doc), util::exception);

    char nan[] = "[8.28369, y]";
    doc.Parse(nan);
    BOOST_CHECK_THROW(util::validateCoordinate(doc), util::exception);
}

BOOST_AUTO_TEST_CASE(timezone_validation_test)
{
    char json[] =
        "{ \"type\" : \"Feature\","
        "\"properties\" : { \"TZID\" : \"Europe/Berlin\"}, \"geometry\" : { \"type\": \"polygon\", "
        "\"coordinates\": [[[8.28369,48.88277], [8.57757, "
        "48.88277], [8.57757, 49.07206], [8.28369, "
        "49.07206], [8.28369, 48.88277]]] }}";
    rapidjson::Document doc;
    doc.Parse(json);
    BOOST_CHECK_NO_THROW(util::validateFeature(doc));

    char missing_type[] = "{\"properties\" : { \"TZID\" : \"Europe/Berlin\"}, \"geometry\" : { "
                          "\"type\": \"polygon\", "
                          "\"coordinates\": [[[8.28369,48.88277], [8.57757, "
                          "48.88277], [8.57757, 49.07206], [8.28369, "
                          "49.07206], [8.28369, 48.88277]]] }}";
    doc.Parse(missing_type);
    BOOST_CHECK_THROW(util::validateFeature(doc), util::exception);

    char missing_props[] =
        "{ \"type\" : \"Feature\","
        "\"props\" : { \"TZID\" : \"Europe/Berlin\"}, \"geometry\" : { \"type\": \"polygon\", "
        "\"coordinates\": [[[8.28369,48.88277], [8.57757, "
        "48.88277], [8.57757, 49.07206], [8.28369, "
        "49.07206], [8.28369, 48.88277]]] }}";
    doc.Parse(missing_props);
    BOOST_CHECK_THROW(util::validateFeature(doc), util::exception);

    char nonobj_props[] =
        "{ \"type\" : \"Feature\","
        "\"properties\" : [ \"TZID\", \"Europe/Berlin\"], \"geometry\" : { \"type\": \"polygon\", "
        "\"coordinates\": [[[8.28369,48.88277], [8.57757, "
        "48.88277], [8.57757, 49.07206], [8.28369, "
        "49.07206], [8.28369, 48.88277]]] }}";
    doc.Parse(nonobj_props);
    BOOST_CHECK_THROW(util::validateFeature(doc), util::exception);

    char missing_tzid[] = "{ \"type\" : \"Feature\","
                          "\"properties\" : { }, \"geometry\" : { \"type\": \"polygon\", "
                          "\"coordinates\": [[[8.28369,48.88277], [8.57757, "
                          "48.88277], [8.57757, 49.07206], [8.28369, "
                          "49.07206], [8.28369, 48.88277]]] }}";
    doc.Parse(missing_tzid);
    BOOST_CHECK_THROW(util::validateFeature(doc), util::exception);

    char tzid_err[] = "{ \"type\" : \"Feature\","
                      "\"properties\" : { \"TZID\" : []}, \"geometry\" : { \"type\": \"polygon\", "
                      "\"coordinates\": [[[8.28369,48.88277], [8.57757, "
                      "48.88277], [8.57757, 49.07206], [8.28369, "
                      "49.07206], [8.28369, 48.88277]]] }}";
    doc.Parse(tzid_err);
    BOOST_CHECK_THROW(util::validateFeature(doc), util::exception);

    char missing_geom[] = "{ \"type\" : \"Feature\","
                          "\"properties\" : { \"TZID\" : \"Europe/Berlin\"}, \"geometries\" : { "
                          "\"type\": \"polygon\", "
                          "\"coordinates\": [[[8.28369,48.88277], [8.57757, "
                          "48.88277], [8.57757, 49.07206], [8.28369, "
                          "49.07206], [8.28369, 48.88277]]] }}";
    doc.Parse(missing_geom);
    BOOST_CHECK_THROW(util::validateFeature(doc), util::exception);

    char nonobj_geom[] =
        "{ \"type\" : \"Feature\","
        "\"properties\" : { \"TZID\" : \"Europe/Berlin\"}, \"geometry\" : [ \"type\", \"polygon\", "
        "\"coordinates\", [[[8.28369,48.88277], [8.57757, "
        "48.88277], [8.57757, 49.07206], [8.28369, "
        "49.07206], [8.28369, 48.88277]]] ]}";
    doc.Parse(nonobj_geom);
    BOOST_CHECK_THROW(util::validateFeature(doc), util::exception);

    char missing_geom_type[] = "{ \"type\" : \"Feature\","
                               "\"properties\" : { \"TZID\" : \"Europe/Berlin\"}, \"geometry\" : { "
                               "\"no_type\": \"polygon\", "
                               "\"coordinates\": [[[8.28369,48.88277], [8.57757, "
                               "48.88277], [8.57757, 49.07206], [8.28369, "
                               "49.07206], [8.28369, 48.88277]]] }}";
    doc.Parse(missing_geom_type);
    BOOST_CHECK_THROW(util::validateFeature(doc), util::exception);

    char nonstring_geom_type[] = "{ \"type\" : \"Feature\","
                                 "\"properties\" : { \"TZID\" : \"Europe/Berlin\"}, \"geometry\" : "
                                 "{ \"type\": [\"polygon\"], "
                                 "\"coordinates\": [[[8.28369,48.88277], [8.57757, "
                                 "48.88277], [8.57757, 49.07206], [8.28369, "
                                 "49.07206], [8.28369, 48.88277]]] }}";
    doc.Parse(nonstring_geom_type);
    BOOST_CHECK_THROW(util::validateFeature(doc), util::exception);

    char missing_coords[] =
        "{ \"type\" : \"Feature\","
        "\"properties\" : { \"TZID\" : \"Europe/Berlin\"}, \"geometry\" : { \"type\": \"polygon\", "
        "\"coords\": [[[8.28369,48.88277], [8.57757, "
        "48.88277], [8.57757, 49.07206], [8.28369, "
        "49.07206], [8.28369, 48.88277]]] }}";
    doc.Parse(missing_coords);
    BOOST_CHECK_THROW(util::validateFeature(doc), util::exception);

    char missing_outerring[] =
        "{ \"type\" : \"Feature\","
        "\"properties\" : { \"TZID\" : \"Europe/Berlin\"}, \"geometry\" : { \"type\": \"polygon\", "
        "\"coordinates\": [[8.28369,48.88277], [8.57757, "
        "48.88277], [8.57757, 49.07206], [8.28369, "
        "49.07206], [8.28369, 48.88277]] }}";
    doc.Parse(missing_outerring);
    BOOST_CHECK_THROW(util::validateFeature(doc), util::exception);
}
BOOST_AUTO_TEST_SUITE_END()