/**
 *  Licensed under GPL. For more information, see
 *    http://jaxodraw.sourceforge.net/license.html
 *  or the LICENSE file in the jaxodraw distribution.
 */
package net.sf.jaxodraw.object.bezier;

import java.awt.Point;
import java.awt.Rectangle;
import net.sf.jaxodraw.object.AbstractJaxoParticleObjectTest;
import net.sf.jaxodraw.object.arrow.JaxoArrow;
import net.sf.jaxodraw.util.JaxoConstants;


/**
 * Base Test for JaxoBezierObjects.
 */
public abstract class AbstractJaxoBezierObjectTest
    extends AbstractJaxoParticleObjectTest {

    private JaxoBezierObject instance;

    /**
     * Constructor.
     *
     * @param testName The name of this test.
     */
    protected AbstractJaxoBezierObjectTest(String testName) {
        super(testName);
    }

    /** JUnit setup: get a new instance of the object. */
    @Override
    protected void setUp() {
        super.setUp();
        this.instance = (JaxoBezierObject) getInstance();
    }

      //
     // tests
    //

    /** Tests moveBy. */
    public void testMoveBy() {
        instance.setLocation(50, 50, 100, 50, 100, 100, 150, 100);
        instance.moveBy(10, 5);
        assertEquals("Wrong moveBy!", 60, instance.getX());
        assertEquals("Wrong moveBy!", 55, instance.getY());
        assertEquals("Wrong moveBy!", 110, instance.getX2());
        assertEquals("Wrong moveBy!", 55, instance.getY2());
        assertEquals("Wrong moveBy!", 110, instance.getX3());
        assertEquals("Wrong moveBy!", 105, instance.getY3());
        assertEquals("Wrong moveBy!", 160, instance.getX4());
        assertEquals("Wrong moveBy!", 105, instance.getY4());
    }

    /** Tests rescaleObject. */
    public void testRescaleObject() {
        instance.setLocation(50, 50, 100, 50, 100, 100, 150, 100);
        instance.rescaleObject(instance.getX(), instance.getY(), 2.f);
        assertEquals("Bezier x didn't get rescaled right!", 50, instance.getX());
        assertEquals("Bezier x didn't get rescaled right!", 50, instance.getY());
        assertEquals("Bezier x2 didn't get rescaled right!", 150, instance.getX2());
        assertEquals("Bezier y2 didn't get rescaled right!", 50, instance.getY2());
        assertEquals("Bezier x3 didn't get rescaled right!", 150, instance.getX3());
        assertEquals("Bezier y3 didn't get rescaled right!", 150, instance.getY3());
        assertEquals("Bezier x4 didn't get rescaled right!", 250, instance.getX4());
        assertEquals("Bezier y4 didn't get rescaled right!", 150, instance.getY4());
    }

    /** Tests getGrabbedHandle. */
    public void testGetGrabbedHandle() {
        instance.setLocation(50, 50, 100, 50, 100, 100, 150, 100);
        checkHandle(50, 50, JaxoBezierObject.SELECT_P1);
        checkHandle(100, 50, JaxoBezierObject.SELECT_P2);
        checkHandle(100, 100, JaxoBezierObject.SELECT_P3);
        checkHandle(150, 100, JaxoBezierObject.SELECT_P4);
        checkHandle(500, 500, JaxoBezierObject.SELECT_NONE);
    }

    /** Tests canBeSelected. */
    public void testCanBeSelected() {
        int mode = JaxoConstants.MOVE;
        assertTrue("Can select P1 in MOVE mode",
            instance.canBeSelected(JaxoBezierObject.SELECT_P1, mode));
        assertTrue("Can select P4 in MOVE mode",
            instance.canBeSelected(JaxoBezierObject.SELECT_P4, mode));
        assertFalse("Can't select P2 in MOVE mode",
            instance.canBeSelected(JaxoBezierObject.SELECT_P2, mode));
        assertFalse("Can't select P3 in MOVE mode",
            instance.canBeSelected(JaxoBezierObject.SELECT_P3, mode));

        mode = JaxoConstants.RESIZE;
        assertTrue("Can select P2 in RESIZE mode",
            instance.canBeSelected(JaxoBezierObject.SELECT_P2, mode));
        assertTrue("Can select P3 in RESIZE mode",
            instance.canBeSelected(JaxoBezierObject.SELECT_P3, mode));
    }

    /** Tests smallestDistanceTo. */
    public void testSmallestDistanceTo() {
        instance.setLocation(50, 50, 100, 50, 100, 100, 150, 100);
        float dist = instance.smallestDistanceTo(45, 50);
        assertEquals("Wrong distance", dist, 5.f);
        dist = instance.smallestDistanceTo(105, 50);
        assertEquals("Wrong distance", dist, 5.f);
        dist = instance.smallestDistanceTo(105, 100);
        assertEquals("Wrong distance", dist, 5.f);
        dist = instance.smallestDistanceTo(155, 100);
        assertEquals("Wrong distance", dist, 5.f);
    }

    /** Tests all getters/setters. */
    public void testGetSetXY() {
        assertEquals("Wrong PointCount!", 4, instance.getPointCount());
        try {
            instance.setPointCount(3);
            fail("setPointCount(3) should throw IllegalArgumentException");
        } catch (IllegalArgumentException e) {
            // expected, now check it doesn't throw with proper value
            instance.setPointCount(4);
        }
        try {
            instance.getX(4);
            fail("getX(4) should throw IllegalArgumentException");
        } catch (IllegalArgumentException e) {
            // expected, now check it doesn't throw with proper value
            instance.getX(3);
        }
        try {
            instance.getY(4);
            fail("getY(4) should throw IllegalArgumentException");
        } catch (IllegalArgumentException e) {
            // expected, now check it doesn't throw with proper value
            instance.getY(3);
        }
        int value = 0;
        instance.setX(3, value);
        instance.setY(3, value);
        assertEquals("Wrong x4!", value, instance.getX(3));
        assertEquals("Wrong y4!", value, instance.getY(3));
        instance.setX(2, value);
        instance.setY(2, value);
        assertEquals("Wrong x3!", value, instance.getX(2));
        assertEquals("Wrong y3!", value, instance.getY(2));
        instance.setX(1, value);
        instance.setY(1, value);
        assertEquals("Wrong x1!", value, instance.getX(1));
        assertEquals("Wrong y1!", value, instance.getY(1));
        instance.setX(0, value);
        instance.setY(0, value);
        assertEquals("Wrong x!", value, instance.getX(0));
        assertEquals("Wrong y!", value, instance.getY(0));
        try {
            instance.setX(4, value);
            fail("setX(4, value) should throw IllegalArgumentException");
        } catch (IllegalArgumentException e) {
            // expected, now check it doesn't throw with proper value
            instance.setX(3, value);
        }
        try {
            instance.setY(4, value);
            fail("setY(4, value) should throw IllegalArgumentException");
        } catch (IllegalArgumentException e) {
            // expected, now check it doesn't throw with proper value
            instance.setY(3, value);
        }
    }

    /** {@inheritDoc} */
    public void testContains() {
        instance.setLocation(50, 50, 100, 50, 100, 100, 150, 100);

        assertTrue(getInstance().contains(75, 75));
        assertFalse(getInstance().contains(5, 5));

        assertTrue(getInstance().contains(75, 75, 5, 5));
        assertFalse(getInstance().contains(5, 5, 5, 5));

        assertTrue(getInstance().contains(new Point(75, 75)));
        assertFalse(getInstance().contains(new Point(5, 5)));

        assertTrue(getInstance().contains(new Rectangle(75, 75, 5, 5)));
        assertFalse(getInstance().contains(new Rectangle(5, 5, 5, 5)));
    }

    /** {@inheritDoc} */
    public void testIntersects() {
        instance.setLocation(50, 50, 100, 50, 100, 100, 150, 100);

        assertTrue(getInstance().intersects(5, 5, 100, 100));
        assertFalse(getInstance().intersects(5, 5, 10, 10));

        assertTrue(getInstance().intersects(new Rectangle(130, 130)));
        assertFalse(getInstance().intersects(new Rectangle(30, 30)));
    }

    /** {@inheritDoc} */
    @Override
    public String[] serializableProperties() {
        return new String[] {
            "DLSeparation", "amp", "arrow", "arrowPosition", "color",
            "dash", "doubleLine", "flip", "paintArrow", "pointCount",
            "points", "strokeWidth", "wiggles", "noFreqStretching"
        }; // 14
    }

    /** {@inheritDoc} */
    public void testArrowCoordinates() {
        instance.setLocation(50, 50, 100, 50, 100, 100, 150, 100);

        instance.setArrowPosition(0.f);
        JaxoArrow.Coordinates arrow = instance.arrowCoordinates();
        assertEquals(50, (int) Math.round(arrow.getX()));
        assertEquals(50, (int) Math.round(arrow.getY()));
        assertEquals(0.f, (float) arrow.getAngle());

        instance.setArrowPosition(0.5f);
        arrow = instance.arrowCoordinates();
        assertEquals(100, (int) Math.round(arrow.getX()));
        assertEquals(75, (int) Math.round(arrow.getY()));
        assertEquals((float) (Math.PI / 4.d), (float) arrow.getAngle());

        instance.setArrowPosition(1.f);
        arrow = instance.arrowCoordinates();
        assertEquals(150, (int) Math.round(arrow.getX()));
        assertEquals(100, (int) Math.round(arrow.getY()));
        assertEquals(0.f, (float) arrow.getAngle());
    }

      //
     // abstract
    //

    /** Tests serialization. */
    public abstract void testSerialization();

}
