//
// Test Suite for C-API GEOSReverse
#include <tut/tut.hpp>
// geos
#include <geos_c.h>
// std
#include <cstdarg>
#include <cstdio>
#include <cstdlib>

namespace tut
{
    //
    // Test Group
    //

    // Common data used in test cases.
    struct test_capigeosreverse
    {
        static void notice(const char *fmt, ...)
        {
            std::fprintf( stdout, "NOTICE: ");

            va_list ap;
            va_start(ap, fmt);
            std::vfprintf(stdout, fmt, ap);
            va_end(ap);

            std::fprintf(stdout, "\n");
        }

        test_capigeosreverse()
        {
            initGEOS(notice, notice);
        }

        ~test_capigeosreverse()
        {
            finishGEOS();
        }
    };

    typedef test_group<test_capigeosreverse> group;
    typedef group::object object;

    group test_capigeosreverse_group("capi::GEOSReverse");

    void testReverse(const std::string & wkt_input,
                     const std::string & wkt_output)
    {
        GEOSGeometry* input = GEOSGeomFromWKT(wkt_input.c_str());
        GEOSGeometry* expected_result = GEOSGeomFromWKT(wkt_output.c_str());
        GEOSGeometry* result = GEOSReverse(input);

        ensure(result != nullptr);
        ensure_equals(1, GEOSEqualsExact(result, expected_result, 0.0));

        GEOSGeom_destroy(input);
        GEOSGeom_destroy(expected_result);
        GEOSGeom_destroy(result);
    }

    //
    // Test Cases
    //
    template<>
    template<>
    void object::test<1>()
    {
        testReverse("POINT (3 5)", "POINT (3 5)");
    }

    template<>
    template<>
    void object::test<2>()
    {
        testReverse("MULTIPOINT ((100 100), (10 100), (30 100))",
                    "MULTIPOINT ((100 100), (10 100), (30 100))");
    }

    template<>
    template<>
    void object::test<3>()
    {
        testReverse("LINESTRING (200 200, 200 100)",
                    "LINESTRING (200 100, 200 200)");
    }

    template<>
    template<>
    void object::test<4>()
    {
        testReverse("MULTILINESTRING ((1 1, 2 2), (3 3, 4 4))",
                    "MULTILINESTRING ((4 4, 3 3), (2 2, 1 1))");
    }

    template<>
    template<>
    void object::test<5>()
    {
        testReverse("POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0), (1 1, 2 1, 2 2, 1 2, 1 1))",
                    "POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1))");

    }

    template<>
    template<>
    void object::test<6>()
    {
        testReverse("MULTIPOLYGON (((0 0, 10 0, 10 10, 0 10, 0 0), (1 1, 2 1, 2 2, 1 2, 1 1)), ((100 100, 100 200, 200 200, 100 100)))",
                    "MULTIPOLYGON (((0 0, 0 10, 10 10, 10 0, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1)), ((100 100, 200 200, 100 200, 100 100)))");

    }

    template<>
    template<>
    void object::test<7>()
    {
        testReverse("GEOMETRYCOLLECTION (LINESTRING (1 1, 2 2), GEOMETRYCOLLECTION(LINESTRING (3 5, 2 9)))",
                    "GEOMETRYCOLLECTION (LINESTRING (2 2, 1 1), GEOMETRYCOLLECTION(LINESTRING (2 9, 3 5)))");

    }

    template<>
    template<>
    void object::test<8>()
    {
        testReverse("POINT EMPTY",              "POINT EMPTY");
        testReverse("LINESTRING EMPTY",         "LINESTRING EMPTY");
        testReverse("LINEARRING EMPTY",         "LINEARRING EMPTY");
        testReverse("POLYGON EMPTY",            "POLYGON EMPTY");
        testReverse("MULTIPOINT EMPTY",         "MULTIPOINT EMPTY");
        testReverse("MULTILINESTRING EMPTY",    "MULTILINESTRING EMPTY");
        testReverse("MULTIPOLYGON EMPTY",       "MULTIPOLYGON EMPTY");
        testReverse("GEOMETRYCOLLECTION EMPTY", "GEOMETRYCOLLECTION EMPTY");
    }

} // namespace tut
