//
// Test Suite for geos::geom::PrecisionModel class.

// tut
#include <tut/tut.hpp>
// geos
#include <geos/geom/PrecisionModel.h>
#include <geos/geom/Coordinate.h>

namespace tut
{
    //
    // Test Group
    //

    // Common data used by tests
    struct test_precisionmodel_data
    {
        typedef geos::geom::PrecisionModel PrecisionModel;
        typedef geos::geom::Coordinate Coordinate;
        test_precisionmodel_data() {}

        void preciseCoordinateTester(const PrecisionModel& pm,
                      double x1, double y1,
                      double x2, double y2)
        {
              Coordinate p(x1, y1);

              pm.makePrecise(p);

              Coordinate pPrecise(x2, y2);
              ensure(p.equals2D(pPrecise));
        }


    };

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

    group test_precisionmodel_group("geos::geom::PrecisionModel");

    //
    // Test Cases
    //

    // Test of default constructor
    template<>
    template<>
    void object::test<1>()
    {
        PrecisionModel pm;
        ensure(pm.isFloating());
        ensure_equals(pm.getMaximumSignificantDigits(), 16);
        ensure_equals(pm.getScale(), 0);
    }

    // Test FLOAT_SINGLE model
    template<>
    template<>
    void object::test<2>()
    {
        PrecisionModel pm(PrecisionModel::FLOATING_SINGLE);
        ensure(pm.isFloating());
        ensure_equals(pm.getType(), PrecisionModel::FLOATING_SINGLE);
        ensure_equals(pm.getMaximumSignificantDigits(), 6);
    }

    // Test default FIXED model
    template<>
    template<>
    void object::test<3>()
    {
        PrecisionModel pm(PrecisionModel::FIXED);
        ensure(!pm.isFloating());
        ensure_equals(pm.getType(), PrecisionModel::FIXED);
        ensure_equals(pm.getMaximumSignificantDigits(), 0);
    }

    // Test maximum significant digits (1:0)
    template<>
    template<>
    void object::test<4>()
    {
        PrecisionModel pm(1);
        ensure(!pm.isFloating());
        ensure_equals(pm.getType(), PrecisionModel::FIXED);
        ensure_equals(pm.getMaximumSignificantDigits(), 0);
    }

    // Test maximum significant digits (10:1)
    template<>
    template<>
    void object::test<5>()
    {
        PrecisionModel pm(10);
        ensure_equals(pm.getType(), PrecisionModel::FIXED);
        ensure_equals(pm.getMaximumSignificantDigits(), 1);
    }

    // Test maximum significant digits (1000:3)
    template<>
    template<>
    void object::test<6>()
    {
        PrecisionModel pm(1000);
        ensure_equals(pm.getType(), PrecisionModel::FIXED);
        ensure_equals(pm.getMaximumSignificantDigits(), 3);
    }

    // Test maximum significant digits (0.1:-1)
    template<>
    template<>
    void object::test<7>()
    {
        PrecisionModel pm(0.1);
        ensure_equals(pm.getType(), PrecisionModel::FIXED);
        ensure_equals(pm.getMaximumSignificantDigits(), -1);
    }

    // Test maximum significant digits (0.001:-3)
    template<>
    template<>
    void object::test<8>()
    {
        PrecisionModel pm(0.001);
        ensure_equals(pm.getType(), PrecisionModel::FIXED);
        ensure_equals(pm.getMaximumSignificantDigits(), -3);
    }

    // Test makePrecise
    template<>
    template<>
    void object::test<9>()
    {
        PrecisionModel pm_10(0.1);
        preciseCoordinateTester(pm_10, 1200.4, 1240.4, 1200, 1240);
        preciseCoordinateTester(pm_10, 1209.4, 1240.4, 1210, 1240);
    }

} // namespace tut

