package seng302.Model;

import javafx.scene.paint.Color;
import org.junit.Test;
import seng302.GPSCoordinate;

import static junit.framework.TestCase.*;

/**
 * Created by esa46 on 22/03/17.
 */
public class BoatInRaceTest {


    private final GPSCoordinate ORIGIN_COORDS = new GPSCoordinate(0, 0);
    private final BoatInRace TEST_BOAT = new BoatInRace("Test", 1, Color.ALICEBLUE, "tt");


    @Test
    public void calculateDueNorthAzimuthReturns0() {

        Marker startMarker = new Marker(ORIGIN_COORDS);
        Marker endMarker = new Marker(new GPSCoordinate(50, 0));
        Leg start = new Leg("Start", startMarker, endMarker, 0);
        TEST_BOAT.setCurrentLeg(start);
        assertEquals(TEST_BOAT.calculateAzimuth(), 0, 1e-8);
    }

    @Test
    public void calculateDueSouthAzimuthReturns180() {
        Marker startMarker = new Marker(ORIGIN_COORDS);
        Marker endMarker = new Marker(new GPSCoordinate(-50, 0));
        Leg start = new Leg("Start", startMarker, endMarker, 0);
        TEST_BOAT.setCurrentLeg(start);
        assertEquals(TEST_BOAT.calculateAzimuth(), 180, 1e-8);
    }


    @Test
    public void calculateDueEastAzimuthReturns90() {

        Marker startMarker = new Marker(ORIGIN_COORDS);
        Marker endMarker = new Marker(new GPSCoordinate(0, 50));
        Leg start = new Leg("Start", startMarker, endMarker, 0);
        TEST_BOAT.setCurrentLeg(start);
        assertEquals(TEST_BOAT.calculateAzimuth(), 90, 1e-8);
    }


    @Test
    public void calculateDueWestAzimuthReturnsNegative90() {
        Marker startMarker = new Marker(ORIGIN_COORDS);
        Marker endMarker = new Marker(new GPSCoordinate(0, -50));
        Leg start = new Leg("Start", startMarker, endMarker, 0);
        TEST_BOAT.setCurrentLeg(start);
        assertEquals(TEST_BOAT.calculateAzimuth(), -90, 1e-8);

    }

    @Test
    public void calculateDueNorthHeadingReturns0() {

        Marker startMarker = new Marker(ORIGIN_COORDS);
        Marker endMarker = new Marker(new GPSCoordinate(50, 0));
        Leg start = new Leg("Start", startMarker, endMarker, 0);
        TEST_BOAT.setCurrentLeg(start);
        assertEquals(TEST_BOAT.calculateHeading(), 0, 1e-8);
    }


    @Test
    public void calculateDueEastHeadingReturns90() {
        Marker startMarker = new Marker(ORIGIN_COORDS);
        Marker endMarker = new Marker(new GPSCoordinate(0, 50));
        Leg start = new Leg("Start", startMarker, endMarker, 0);
        TEST_BOAT.setCurrentLeg(start);
        assertEquals(TEST_BOAT.calculateHeading(), 90, 1e-8);
    }

    @Test
    public void calculateDueSouthHeadingReturns180() {
        Marker startMarker = new Marker(ORIGIN_COORDS);
        Marker endMarker = new Marker(new GPSCoordinate(-50, 0));
        Leg start = new Leg("Start", startMarker, endMarker, 0);
        TEST_BOAT.setCurrentLeg(start);
        assertEquals(TEST_BOAT.calculateHeading(), 180, 1e-8);
    }

    @Test
    public void calculateDueWestHeadingReturns270() {
        Marker startMarker = new Marker(ORIGIN_COORDS);
        Marker endMarker = new Marker(new GPSCoordinate(0, -50));
        Leg start = new Leg("Start", startMarker, endMarker, 0);
        TEST_BOAT.setCurrentLeg(start);
        assertEquals(TEST_BOAT.calculateHeading(), 270, 1e-8);
    }

    @Test
    public void createNewBoatCratesInstanceOfSuperClass() {

        BoatInRace testBoat = new BoatInRace("Boat", 20, Color.ALICEBLUE, "tt");
        testBoat.setName("Name can change");
        assertTrue(testBoat instanceof Boat);
        assertTrue(testBoat.getCurrentLeg() == null);
        assertTrue(testBoat.getCurrentPosition() == null);
        assertTrue(testBoat.toString().contains("Name can change"));
        assertEquals(testBoat.getVelocity(), 20.0);
        assertTrue(testBoat.getVelocityProp().toString().contains("20"));
        assertTrue(testBoat.getAbbrev().equals("tt"));
        assertTrue(testBoat.getColour().equals(Color.ALICEBLUE));
        assertFalse(testBoat.isFinished());
    }


    @Test
    public void getWakeAtProperHeading() throws Exception {
        BoatInRace boat = new BoatInRace("Test", 1, Color.ALICEBLUE, "tt");

        // Construct leg of 0 degrees
        Marker startMarker = new Marker(ORIGIN_COORDS);
        Marker endMarker = new Marker(new GPSCoordinate(50, 0));
        Leg leg0deg = new Leg("Start", startMarker, endMarker, 0);
        boat.setCurrentLeg(leg0deg);
        boat.setCurrentPosition(new GPSCoordinate(0, 0));

        assertEquals(0, boat.calculateHeading(), 1e-8);

        // Construct leg from wake - heading should be 180 degrees
        Leg leg180deg = new Leg("Start", startMarker, new Marker(boat.getWake()), 0);
        boat.setCurrentLeg(leg180deg);

        assertEquals(180, boat.calculateHeading(), 1e-8);
    }


    @Test
    public void getWakeProportionalToVelocity() throws Exception {
        BoatInRace boat = new BoatInRace("Test", 10, Color.ALICEBLUE, "tt");

        // Construct leg of 0 degrees at 0 N
        Marker startMarker = new Marker(ORIGIN_COORDS);
        Marker endMarker = new Marker(new GPSCoordinate(50, 0));
        Leg leg0deg = new Leg("Start", startMarker, endMarker, 0);
        boat.setCurrentLeg(leg0deg);
        boat.setCurrentPosition(new GPSCoordinate(0, 0));

        // Get latitude of endpoint of wake at 10 kn (longitude is 0)
        double endpointAt10Kn = boat.getWake().getLatitude();

        // Latitude of endpoint at 20 kn should be twice endpoint at 10 kn
        boat.setVelocity(20);
        assertEquals(2 * endpointAt10Kn, boat.getWake().getLatitude(), 1e-8);
    }
}