package scheduler;

import static org.junit.Assert.*;

import java.util.Arrays;
import java.util.HashMap;

import org.junit.Before;
import org.junit.Test;

import common.Direction;
import common.Motor;

public class MetaElevatorTest {

	private MetaElevator me;

	@Before
	public void setUp() throws Exception {
		SystemGUI.createSystemGUI(1, 15, false);
	}

	@Test
	public void testAddDestinationFloor() throws Exception {
		me = new MetaElevator(1, 6);
		me.setMotorStatus(Motor.DOWN);
		me.addDestinationFloor(15, Direction.DOWN);
		me.addDestinationFloor(3, Direction.DOWN);
		me.addDestinationFloor(5, Direction.DOWN);
		me.addDestinationFloor(7, Direction.UP);
		me.addDestinationFloor(9, Direction.UP);
		me.addDestinationFloor(2, Direction.DOWN);

		assertEquals(Arrays.asList(7, 9), me.getDestinations(Direction.UP));
		assertEquals(Arrays.asList(15, 5, 3, 2), me.getDestinations(Direction.DOWN));
	}

	@Test
	public void testRemoveDestinationFloor() {
		me = new MetaElevator(1, 1);
		me.setMotorStatus(Motor.DOWN);
		me.addDestinationFloor(15, Direction.DOWN);
		me.addDestinationFloor(3, Direction.DOWN);
		me.addDestinationFloor(5, Direction.DOWN);
		me.addDestinationFloor(7, Direction.UP);
		me.addDestinationFloor(9, Direction.UP);
		me.addDestinationFloor(2, Direction.DOWN);

		assertEquals(Arrays.asList(15, 5, 3, 2), me.getDestinations(Direction.DOWN));
		me.removeDestinationFloor(); // remove the next down request
		assertEquals(Arrays.asList(7, 9), me.getDestinations(Direction.UP));
		assertEquals(Arrays.asList(5, 3, 2), me.getDestinations(Direction.DOWN));

		me.setMotorStatus(Motor.UP);
		me.removeDestinationFloor(); // remove the next up request
		assertEquals(Arrays.asList(9), me.getDestinations(Direction.UP));
		assertEquals(Arrays.asList(5, 3, 2), me.getDestinations(Direction.DOWN));

		me.clearDestinations(Direction.UP);
		me.removeDestinationFloor(); // since no more in up, remove next down request
		assertEquals(Arrays.asList(), me.getDestinations(Direction.UP));
		assertEquals(Arrays.asList(3, 2), me.getDestinations(Direction.DOWN));

		me.setMotorStatus(Motor.DOWN);
		me.addDestinationFloor(4, Direction.UP);
		me.addDestinationFloor(6, Direction.UP);
		me.clearDestinations(Direction.DOWN);
		me.removeDestinationFloor(); // since no more in down, remove next up request
		assertEquals(Arrays.asList(6), me.getDestinations(Direction.UP));
		assertEquals(Arrays.asList(), me.getDestinations(Direction.DOWN));
	}

	@Test
	public void testGetNextDestination() {
		me = new MetaElevator(1, 1);

		me.addDestinationFloor(2, Direction.UP);
		me.addDestinationFloor(2, Direction.DOWN);
		me.addDestinationFloor(5, Direction.UP);
		me.addDestinationFloor(6, Direction.DOWN);

		me.setMotorStatus(Motor.DOWN);
		assertEquals(6, me.getNextDestination());

		me.setMotorStatus(Motor.UP);
		assertEquals(2, me.getNextDestination());

		me.clearDestinations(Direction.UP);
		assertEquals(6, me.getNextDestination());

		me.addDestinationFloor(5, Direction.UP);
		me.setMotorStatus(Motor.DOWN);
		me.clearDestinations(Direction.DOWN);
		assertEquals(5, me.getNextDestination());
	}

	@Test
	public void testGetDestinationsForReroute() {
		me = new MetaElevator(1, 1);

		// these should be rerouted
		me.addDestinationFloor(2, Direction.UP);
		me.addDestinationFloor(3, Direction.DOWN);

		me.addDestinationFloor(6, null);
		me.addDestinationFloor(4, null);

		HashMap<Integer, Direction> expected = new HashMap<>();
		expected.put(2, Direction.UP);
		expected.put(3, Direction.DOWN);
		assertEquals(expected, me.getDestinationsForReroute());
	}

}
