package jrummikub.control;

import static org.junit.Assert.*;

import java.util.Collections;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;

import jrummikub.model.Stone;
import jrummikub.model.StoneColor;
import jrummikub.util.Event;
import jrummikub.util.IEvent;
import jrummikub.util.IListener;
import jrummikub.view.MockView;

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

public class TurnControlTest {

	class MockTimer implements ITurnTimer {
		public boolean timerRunning;
		public Event timeRunOutEvent = new Event();

		@Override
		public void startTimer() {
			timerRunning = true;
		}

		@Override
		public void stopTimer() {
			timerRunning = false;
		}

		@Override
		public IEvent getTimeRunOutEvent() {
			return timeRunOutEvent;
		}

	}

	MockView mockView;
	MockTimer mockTimer;
	boolean eventFired;

	@Before
	public void setUp() {
		mockView = new MockView();
		mockTimer = new MockTimer();
	}

	@Test
	public void viewEndOfTurn() {
		eventFired = false;
		mockTimer.timerRunning = true;
		TurnControl testControl = new TurnControl(null, null, mockView,
				mockTimer);

		testControl.getEndOfTurnEvent().add(new IListener() {

			@Override
			public void handle() {
				eventFired = true;
			}
		});

		mockView.playerPanel.endTurnEvent.emit();

		assertTrue(eventFired);
		assertFalse(mockTimer.timerRunning);
	}

	@Test
	public void timerEndOfTurn() {
		eventFired = false;
		mockTimer.timerRunning = true;
		TurnControl testControl = new TurnControl(null, null, mockView,
				mockTimer);

		testControl.getEndOfTurnEvent().add(new IListener() {

			@Override
			public void handle() {
				eventFired = true;
			}
		});

		mockTimer.timeRunOutEvent.emit();

		assertTrue(eventFired);
		assertFalse(mockTimer.timerRunning);
	}

	@Test
	public void selectStoneInHand() {
		TurnControl testControl = new TurnControl(null, null, mockView,
				mockTimer);

		Stone firstStone = new Stone(StoneColor.RED);

		// Select first stone
		mockView.playerPanel.handPanel.stoneClickEvent.emit(firstStone, false);

		assertCollection(Arrays.asList(firstStone));

		// Select second stone
		Stone secondStone = new Stone(StoneColor.BLACK);
		mockView.playerPanel.handPanel.stoneClickEvent.emit(secondStone, false);

		assertCollection(Arrays.asList(secondStone));

	}

	@Test
	public void collectStoneInHand() {
		TurnControl testControl = new TurnControl(null, null, mockView,
				mockTimer);

		Stone firstStone = new Stone(StoneColor.RED);

		// Select first stone
		mockView.playerPanel.handPanel.stoneClickEvent.emit(firstStone, true);

		assertCollection(Arrays.asList(firstStone));

		// Select second stone
		Stone secondStone = new Stone(StoneColor.BLACK);
		mockView.playerPanel.handPanel.stoneClickEvent.emit(secondStone, true);

		assertCollection(Arrays.asList(firstStone, secondStone));

		// De-select first stone
		mockView.playerPanel.handPanel.stoneClickEvent.emit(firstStone, true);

		assertCollection(Arrays.asList(secondStone));
	}

	@Test
	public void deselectStoneInCollection() {
		TurnControl testControl = new TurnControl(null, null, mockView,
				mockTimer);
		Stone firstStone = new Stone(StoneColor.RED);
		Stone secondStone = new Stone(StoneColor.BLACK);

		mockView.playerPanel.handPanel.stoneClickEvent.emit(firstStone, true);
		mockView.playerPanel.handPanel.stoneClickEvent.emit(secondStone, true);

		mockView.tablePanel.stoneCollectionPanel.stoneClickEvent.emit(
				firstStone, false);

		assertCollection(Arrays.asList(secondStone));
	}
	
	@Test
	public void reorderCollection() {

		TurnControl testControl = new TurnControl(null, null, mockView,
				mockTimer);
		Stone firstStone = new Stone(StoneColor.RED);
		Stone secondStone = new Stone(StoneColor.BLACK);

		mockView.playerPanel.handPanel.stoneClickEvent.emit(firstStone, true);
		mockView.playerPanel.handPanel.stoneClickEvent.emit(secondStone, true);

		mockView.tablePanel.stoneCollectionPanel.stoneClickEvent.emit(
				firstStone, true);

		assertCollection(Arrays.asList(secondStone, firstStone));
	}
	
	@Test
	public void deselectWholeCollection() {

		TurnControl testControl = new TurnControl(null, null, mockView,
				mockTimer);
		Stone firstStone = new Stone(StoneColor.RED);
		Stone secondStone = new Stone(StoneColor.BLACK);

		mockView.playerPanel.handPanel.stoneClickEvent.emit(firstStone, true);
		mockView.playerPanel.handPanel.stoneClickEvent.emit(secondStone, true);

		mockView.tablePanel.stoneCollectionPanel.setClickEvent.emit(
				firstStone, true);

		assertCollection(new ArrayList<Stone>());
	}
	

	private void assertCollection(List<Stone> expected) {
		ArrayList<Stone> selectedStones = new ArrayList<Stone>(
				mockView.selectedStones);
		ArrayList<Stone> expectedStones = new ArrayList<Stone>(expected);
		assertEquals(selectedStones, expectedStones);
	}
}