package mock.model;

import mock.dataInput.PolarParser;
import mock.exceptions.InvalidPolarFileException;
import org.junit.Before;
import org.junit.Test;
import shared.model.Bearing;
import shared.model.CompoundMark;
import shared.model.GPSCoordinate;
import shared.model.Mark;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

public class MockBoatTest {

    /**
     * boat made for testing
     */
    private MockBoat firstTestBoat;

    private Mark markToTest;
    private Mark markToTest2;

    private GPSCoordinate highGPS;
    private GPSCoordinate middleGPS;
    private GPSCoordinate lowGPS;

    /**
    * Creates the Polars object for the tests.
    */
    @Before
    public void setUp() {
        //Read in polars.
        try {
            //Parse data file.
            Polars polars = PolarParser.parse("mock/polars/acc_polars.csv");

            firstTestBoat = new MockBoat(1, "test", "NZ", polars);
            highGPS = new GPSCoordinate(32.296577, -64.854000);
            middleGPS = new GPSCoordinate(32.292500, -64.854000);
            lowGPS = new GPSCoordinate(32.290000, -64.854000);
            markToTest = new Mark(1, "test MARK", middleGPS);
            markToTest2 = new Mark(2, "test MARK2", middleGPS);
        }
        catch (InvalidPolarFileException e) {
            fail("Couldn't parse polar file.");
        }
    }

    //////////////////////////////Mark Higher////////////////////////////////

    /**
     * Tests if the boat is lower than the mark that the port side method works if
     * boat is facing east
     */
    @Test
    public void testIsPortSide() {
        firstTestBoat.setBearing(Bearing.fromDegrees(90));
        firstTestBoat.setCurrentPosition(lowGPS);
        markToTest.setPosition(highGPS);

        assertEquals(firstTestBoat.isPortSide(markToTest), true);
    }

    /**
     * Tests if the boat is lower than the mark that the port side method works if
     * boat is facing west
     */
    @Test
    public void testIsPortSideWrong() {
        firstTestBoat.setBearing(Bearing.fromDegrees(270));
        firstTestBoat.setCurrentPosition(lowGPS);
        markToTest.setPosition(highGPS);

        assertEquals(firstTestBoat.isPortSide(markToTest), false);
    }

    /**
     * Tests if the boat is lower than the mark that the starboard side method works if
     * boat is facing east
     */
    @Test
    public void testIsStarboardSideWrong() {
        firstTestBoat.setBearing(Bearing.fromDegrees(90));
        firstTestBoat.setCurrentPosition(lowGPS);
        markToTest.setPosition(highGPS);

        assertEquals(firstTestBoat.isStarboardSide(markToTest), false);
    }

    /**
     * Tests if the boat is lower than the mark that the starboard side method works if
     * boat is facing west
     */
    @Test
    public void testIsStarboardSide() {
        firstTestBoat.setBearing(Bearing.fromDegrees(270));
        firstTestBoat.setCurrentPosition(lowGPS);
        markToTest.setPosition(highGPS);

        assertEquals(firstTestBoat.isStarboardSide(markToTest), true);
    }


    //////////////////////////////Mark Lower////////////////////////////////

    /**
     * Tests if the boat is higher than the mark that the port side method works if
     * boat is facing east
     */
    @Test
    public void testIsPortSideHigherWrong() {
        firstTestBoat.setBearing(Bearing.fromDegrees(90));
        firstTestBoat.setCurrentPosition(highGPS);
        markToTest.setPosition(lowGPS);

        assertEquals(firstTestBoat.isPortSide(markToTest), false);
    }

    /**
     * Tests if the boat is higher than the mark that the port side method works if
     * boat is facing west
     */
    @Test
    public void testIsPortSideHigher() {
        firstTestBoat.setBearing(Bearing.fromDegrees(270));
        firstTestBoat.setCurrentPosition(highGPS);
        markToTest.setPosition(lowGPS);

        assertEquals(firstTestBoat.isPortSide(markToTest), true);
    }

    /**
     * Tests if the boat is higher than the mark that the starboard side method works if
     * boat is facing east
     */
    @Test
    public void testIsStarboardSideHigher() {
        firstTestBoat.setBearing(Bearing.fromDegrees(90));
        firstTestBoat.setCurrentPosition(highGPS);
        markToTest.setPosition(lowGPS);

        assertEquals(firstTestBoat.isStarboardSide(markToTest), true);
    }

    /**
     * Tests if the boat is higher than the mark that the starboard side method works if
     * boat is facing west
     */
    @Test
    public void testIsStarboardSideHigherWrong() {
        firstTestBoat.setBearing(Bearing.fromDegrees(270));
        firstTestBoat.setCurrentPosition(highGPS);
        markToTest.setPosition(lowGPS);

        assertEquals(firstTestBoat.isStarboardSide(markToTest), false);
    }

    /**
     * Tests if a boat is between a gate
     */
    @Test
    public void testIsBetweenGate(){
        markToTest.setPosition(highGPS);
        markToTest2.setPosition(lowGPS);
        CompoundMark testGate = new CompoundMark(1, "test GATE", markToTest, markToTest2);

        firstTestBoat.setCurrentPosition(middleGPS);

        assertEquals(firstTestBoat.isBetweenGate(testGate), true);

    }
}
