//
// Test Suite for geos::geom::util::GeometryExtracter class.

// tut
#include <tut/tut.hpp>
// geos
#include <geos/constants.h>
#include <geos/geom/PrecisionModel.h>
#include <geos/geom/GeometryFactory.h>
#include <geos/geom/Point.h>
#include <geos/geom/LineString.h>
#include <geos/geom/Polygon.h>
#include <geos/io/WKTReader.h>
#include <geos/io/WKTWriter.h>
#include <geos/geom/util/GeometryExtracter.h>
// std
#include <vector>

namespace tut {
//
// Test Group
//

// Common data used by tests
struct test_geometryextracter_data {
    geos::geom::PrecisionModel pm;
    geos::geom::GeometryFactory::Ptr gf;
    geos::io::WKTReader wktreader;
    geos::io::WKTWriter wktwriter;

    typedef std::unique_ptr<geos::geom::Geometry> GeomPtr;

    typedef geos::io::WKTReader WKTReader;
    typedef geos::io::WKTWriter WKTWriter;

    test_geometryextracter_data()
        :
        pm(1.0),
        gf(geos::geom::GeometryFactory::create(&pm)),
        wktreader(gf.get())
    {
    }
};

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

group test_geometryextracter_group("geos::geom::util::GeometryExtracter");

//
// Test Cases
//

// Test extraction of single point
template<>
template<>
void object::test<1>
()
{
    using namespace geos::geom::util;
    using namespace geos::geom;

    GeomPtr geom(wktreader.read("POINT(-117 33)"));
    std::vector<const Point*> lst_points;
    std::vector<const LineString*> lst_lines;

    GeometryExtracter::extract<Point>(*geom, lst_points);
    GeometryExtracter::extract<LineString>(*geom, lst_lines);

    ensure_equals(lst_points.size(), 1u);
    ensure_equals(lst_lines.size(), 0u);
}

// Test extraction of multiple types
template<>
template<>
void object::test<2>
()
{
    using namespace geos::geom::util;
    using namespace geos::geom;

    GeomPtr geom(
        wktreader.read("GEOMETRYCOLLECTION(POINT(-117 33),LINESTRING(0 0, 10 0),POINT(0 0),POLYGON((0 0, 10 0, 10 10, 0 10, 0 0)),LINESTRING(10 0, 23 30),POINT(20 20))"));

    std::vector<const Point*> lst_points;
    std::vector<const LineString*> lst_lines;
    std::vector<const Polygon*> lst_polys;

    GeometryExtracter::extract<Point>(*geom, lst_points);
    GeometryExtracter::extract<LineString>(*geom, lst_lines);
    GeometryExtracter::extract<Polygon>(*geom, lst_polys);

    ensure_equals(lst_points.size(), 3u);
    ensure_equals(lst_lines.size(), 2u);
    ensure_equals(lst_polys.size(), 1u);
}

} // namespace tut
