/**
 *  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.fill;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;

import net.sf.jaxodraw.JaxoTestUtils;
import net.sf.jaxodraw.io.imports.JaxoAxodraw;
import net.sf.jaxodraw.object.JaxoObject;
import net.sf.jaxodraw.object.JaxoObjectFactory;
import net.sf.jaxodraw.object.loop.JaxoFLoop;
import net.sf.jaxodraw.util.JaxoColor;
import net.sf.jaxodraw.util.JaxoConstants;
import net.sf.jaxodraw.util.JaxoPrefs;


/** Tests JaxoBox. */
public class JaxoBoxTest extends AbstractJaxoFillObjectTest {
    private JaxoBox box = new JaxoBox();

    /** Constructor: just calls super().
     * @param testName The name of this test.
     */
    public JaxoBoxTest(String testName) {
        super(testName);
    }

    /** JUnit setup: initialize the object. */
    @Override
    protected void setUp() {
        super.setUp();
        init();
    }

    private void init() {
        box.setLocation(100, 100);
        box.setRelWAndH(100, 100);
        box.setStrokeWidth(1.f);
        box.setColor(JaxoColor.GREEN);
        box.setFillColor(JaxoColor.YELLOW);
    }

    /** {@inheritDoc} */
    public JaxoObject getInstance() {
        return box;
    }

    /** Tests serialization. */
    public void testSerialization() {
        box.setLocation(120, 130);
        box.setRelWAndH(10, -100);
        box.setStrokeWidth(5.f);
        box.setColor(JaxoColor.BROWN);
        box.setFillColor(JaxoColor.RED);
        JaxoTestUtils.checkSerializedEquality(box);
    }

    /** Tests that a copy of an object is still the same object. */
    public void testCopy() {
        JaxoBox box2 = new JaxoBox();
        box2.setState(box);

        box.setLocation(120, 130);
        box.setRelWAndH(10, -100);
        box.setStrokeWidth(5.f);
        box.setColor(JaxoColor.BROWN);
        box.setFillColor(JaxoColor.RED);
        JaxoTestUtils.checkCopyEquality(box);

        assertFalse(box2.isCopy(box));

        box2.setLocation(120, 130);
        box2.setRelWAndH(10, -100);
        box2.setStrokeWidth(5.f);
        box2.setColor(JaxoColor.BROWN);
        box2.setFillColor(JaxoColor.RED);
        assertTrue(box2.isCopy(box));

        JaxoFLoop loop = new JaxoFLoop();
        assertFalse(box.isCopy(loop));

    }

    /** Tests identity. */
    public void testIdentity() {
        JaxoBox box2 = box;
        assertEquals(box, box2);
    }

    /** Tests the latex command. */
    public void testLatexCommand() {
        Dimension dim = new Dimension(100, 100);

        String expected = "\\CBox(100,-100)(200,0){Green}{Yellow}";
        String actual = box.latexCommand(1.f, dim);
        assertEquals("Latex commands do not match!", expected, actual);

        box.setColor(JaxoColor.BLACK);
        box.setFillColor(JaxoColor.GRAYSCALE225);
        expected = "\\GBox(100,-100)(200,0){0.882}";
        actual = box.latexCommand(1.f, dim);
        assertEquals("Latex commands do not match!", expected, actual);

        box.setFilled(false);
        expected = "\\EBox(100,-100)(200,0)";
        actual = box.latexCommand(1.f, dim);
        assertEquals("Latex commands do not match!", expected, actual);

        box.setRelWAndH(0, 0);
        expected = "%";
        actual = box.latexCommand(1.f, dim);
        assertEquals("Latex commands do not match!", expected, actual);

    }

    /** Tests axodraw. */
    public void testAxodraw() {
        JaxoAxodraw axo = new JaxoAxodraw();
        JaxoObject ob = axo.getJaxoObject("\\SetWidth{1.0}");
        assertNull(ob);
        String command;

        command = "\\CBox(100,-100)(200,0){Green}{Yellow}";
        box = (JaxoBox) axo.getJaxoObject(command);
        checkBoxParameters(JaxoColor.GREEN, JaxoColor.YELLOW);

        command = "\\GBox(100,-100)(200,0){0.882}";
        box = (JaxoBox) axo.getJaxoObject(command);
        checkBoxParameters(JaxoColor.BLACK, JaxoColor.GRAYSCALE225);

        command = "\\EBox(100,-100)(200,0)";
        box = (JaxoBox) axo.getJaxoObject(command);
        assertFalse("Box should not be filled!", box.isFilled());

    }

    private void checkBoxParameters(Color color, Color fillcolor) {
        assertEquals("Box doesn't have the right color!", color, box.getColor());
        assertEquals("Box doesn't have the right fill color!", fillcolor,
            box.getFillColor());
        assertTrue("Box doesn't have the right stroke!",
            Math.abs(box.getStrokeWidth() - 1.f) < 0.0001f);
        assertEquals("Box doesn't have the right x!", 100, box.getX());
        assertEquals("Box doesn't have the right y!", 0, box.getY());
    }

    /** Tests the getBounds() method. */
    public void testGetBounds() {
        Rectangle bBox = box.getBounds();
        Rectangle expected = new Rectangle(99, 99, 102, 102);
        assertEquals("Bounding box not correct!", expected, bBox);

        assertNotNull(box.getBounds2D());
    }

    /** Tests getGrabbedHandle. */
    public void testGetGrabbedHandle() {
        checkHandle(200, 200, JaxoBox.SELECT_P2);
        checkHandle(100, 200, JaxoBox.SELECT_DX);
        checkHandle(200, 100, JaxoBox.SELECT_DY);
        checkHandle(100, 100, JaxoBox.SELECT_P1);
        checkHandle(500, 500, JaxoBox.SELECT_NONE);

    }

    /** Tests createNewObject in JaxoObjectFactory. */
    public void testCreateNewObject() {
        Point p = new Point(50, 50);
        JaxoObject ob =
            JaxoObjectFactory.newObject(JaxoConstants.BOX, new Point[] {p, p});

        assertTrue("createNewObject did not return a Box!",
            (ob instanceof JaxoBox));

        box = (JaxoBox) ob;
        assertEquals("Box doesn't have the right x!", 50, box.getX());
        assertEquals("Box doesn't have the right y!", 50, box.getY());
        assertEquals("Box doesn't have the right color!",
            JaxoColor.getColor(JaxoPrefs.getStringPref(JaxoPrefs.PREF_COLOR)),
            box.getColor());
        assertEquals("Box doesn't have the right fill color!",
            JaxoColor.GRAYSCALE225, box.getFillColor());
        assertTrue("Box doesn't have the right stroke!",
            box.strokeIs(JaxoPrefs.getFloatPref(JaxoPrefs.PREF_LINEWIDTH)));
    }

    /** Tests canBeSelected. */
    public void testCanBeSelected() {
        int mode = JaxoConstants.MOVE;
        int handle = JaxoBox.SELECT_P1;
        assertTrue("P1 in MOVE mode", box.canBeSelected(handle, mode));
        handle = JaxoBox.SELECT_P2;
        assertTrue("P2 in MOVE mode", box.canBeSelected(handle, mode));
        handle = JaxoBox.SELECT_DX;
        assertTrue("DX in MOVE mode", box.canBeSelected(handle, mode));
        handle = JaxoBox.SELECT_DY;
        assertTrue("DY in MOVE mode", box.canBeSelected(handle, mode));

        mode = JaxoConstants.RESIZE;
        handle = JaxoBox.SELECT_P1;
        assertTrue("P1 in RESIZE mode", box.canBeSelected(handle, mode));
        handle = JaxoBox.SELECT_P2;
        assertTrue("P2 in RESIZE mode", box.canBeSelected(handle, mode));
        handle = JaxoBox.SELECT_DX;
        assertTrue("DX in RESIZE mode", box.canBeSelected(handle, mode));
        handle = JaxoBox.SELECT_DY;
        assertTrue("DY in RESIZE mode", box.canBeSelected(handle, mode));
    }

    /** Tests smallestDistanceTo. */
    @Override
    public void testSmallestDistanceTo() {
        float dist = box.smallestDistanceTo(103, 104);
        assertEquals("Wrong distance", dist, 5.f);
        dist = box.smallestDistanceTo(203, 204);
        assertEquals("Wrong distance", dist, 5.f);
        dist = box.smallestDistanceTo(203, 104);
        assertEquals("Wrong distance", dist, 5.f);
        dist = box.smallestDistanceTo(103, 204);
        assertEquals("Wrong distance", dist, 5.f);
    }

    /** {@inheritDoc} */
    public String className() {
        return "JaxoBox";
    }

    /** {@inheritDoc} */
    public void testJaxo20Compat() {
        JaxoBox object = (JaxoBox) instanceFrom20OpenGraph(JaxoBox.class);
        assertNotNull(object);
        check20Object("opened wrong object!", object);

        object = (JaxoBox) instanceFrom20ImportGraph(JaxoBox.class);
        assertNotNull(object);
        check20Object("opened wrong object!", object);
    }

    private void check20Object(String message, JaxoBox object) {
        assertEquals(message, 473, object.getX());
        assertEquals(message, 43, object.getY());
        assertEquals(message, 547, object.getX2());
        assertEquals(message, 69, object.getY2());

        assertTrue(message, object.strokeIs(1.4f));

        assertEquals(message, JaxoColor.WILDSTRAWBERRY, object.getColor());
        // should the fillcolor be serialized if the box is not filled?
        // the following works with open but not with import
        //assertEquals(message, JaxoColor.MIDNIGHT_BLUE, object.getFillColor());
        assertFalse(message, object.isFilled());
    }

    /** {@inheritDoc} */
    public String[] serializableProperties() {
        return new String[] {
            "color", "fillColor", "filled", "pointCount", "points", "strokeWidth"
        }; // 6
    }
}
