// $Id$
//
// Test Suite for geos::noding::OrientedCoordinateArray class.

#include <tut/tut.hpp>
// geos
#include <geos/noding/OrientedCoordinateArray.h>
#include <geos/io/WKTReader.h>
#include <geos/geom/PrecisionModel.h>
#include <geos/geom/GeometryFactory.h>
#include <geos/geom/Geometry.h>
#include <geos/geom/Coordinate.h>
#include <geos/geom/CoordinateSequence.h>
// std
#include <memory>

using namespace geos::geom;
using namespace geos::noding;

namespace tut {
//
// Test Group
//

// Common data used by all tests
struct test_orientedcoordinatearray_data {
    typedef geos::geom::GeometryFactory GeometryFactory;

    geos::geom::PrecisionModel pm_;
    GeometryFactory::Ptr factory_;
    geos::io::WKTReader reader_;

    typedef std::unique_ptr<CoordinateSequence> CoordSeqPtr;
    typedef std::unique_ptr<Geometry> GeomPtr;

    test_orientedcoordinatearray_data()
        : pm_()
        , factory_(GeometryFactory::create(&pm_))
        , reader_(factory_.get()) {}

    CoordSeqPtr
    coords_from_wkt(const char* wkt)
    {
        GeomPtr g(reader_.read(wkt));
        CoordSeqPtr cs(g->getCoordinates());
        return cs;
    }
};

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

group test_orientedcoordinatearray_group("geos::noding::OrientedCoordinateArray");

//
// Test Cases
//

// Compare to self, closed
template<>
template<>
void object::test<1>
()
{
    const char* coords = "LINESTRING(361600 6126500, 361620 6126560, 361630 6126550, 361620 6126530, 361600 6126500)";
    CoordSeqPtr cs = coords_from_wkt(coords);
    OrientedCoordinateArray oca1(*cs);
    OrientedCoordinateArray oca2(*cs);
    ensure_equals(oca1.compareTo(oca2), 0);
}

// Compare to reverse of self, closed
template<>
template<>
void object::test<2>
()
{
    const char* coords1 = "LINESTRING(361600 6126500, 361620 6126560, 361630 6126550, 361620 6126530, 361600 6126500)";
    const char* coords2 = "LINESTRING(361600 6126500, 361620 6126530, 361630 6126550, 361620 6126560, 361600 6126500)";
    CoordSeqPtr cs1 = coords_from_wkt(coords1);
    OrientedCoordinateArray oca1(*cs1);
    CoordSeqPtr cs2 = coords_from_wkt(coords2);
    OrientedCoordinateArray oca2(*cs2);
    ensure_equals(oca1.compareTo(oca2), 0);
}

// Compare to self, not closed
template<>
template<>
void object::test<3>
()
{
    const char* coords = "LINESTRING(361620 6126560, 361630 6126550, 361620 6126530, 361600 6126500)";
    CoordSeqPtr cs = coords_from_wkt(coords);
    OrientedCoordinateArray oca1(*cs);
    OrientedCoordinateArray oca2(*cs);
    ensure_equals(oca1.compareTo(oca2), 0);
}

// Compare to reverse of self, not closed
template<>
template<>
void object::test<4>
()
{
    const char* coords1 = "LINESTRING(361620 6126560, 361630 6126550, 361620 6126530, 361600 6126500)";
    const char* coords2 = "LINESTRING(361600 6126500, 361620 6126530, 361630 6126550, 361620 6126560)";
    CoordSeqPtr cs1 = coords_from_wkt(coords1);
    OrientedCoordinateArray oca1(*cs1);
    CoordSeqPtr cs2 = coords_from_wkt(coords2);
    OrientedCoordinateArray oca2(*cs2);
    ensure_equals(oca1.compareTo(oca2), 0);
}

// Compare both ways
template<>
template<>
void object::test<5>
()
{
    const char* coords1 = "LINESTRING(0 0, 10 0)";
    const char* coords2 = "LINESTRING(0 0, 10 0, 11 0)";
    CoordSeqPtr cs1 = coords_from_wkt(coords1);
    OrientedCoordinateArray oca1(*cs1);
    CoordSeqPtr cs2 = coords_from_wkt(coords2);
    OrientedCoordinateArray oca2(*cs2);
    ensure_equals(oca1.compareTo(oca2), -1);
    ensure_equals(oca2.compareTo(oca1), 1);
}

} // namespace tut
