package cc.conroy.kf;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;

import javax.swing.JWindow;

public class KidWindow extends JWindow implements MouseListener {
	private static int SIZE = 200;
	
	private GraphicsDevice monitor;

	private Color[] colors = {
	// Purple
			new Color(153, 0, 204),
			// Pink
			new Color(255, 153, 204),
			// Orange
			new Color(255, 153, 0),
			// Red
			new Color(255, 0, 0),
			// Blue
			new Color(0, 0, 255),
			// Green
			new Color(0, 204, 0),
			// Yellow
			new Color(255, 255, 102),
			// Grey
			new Color(153, 153, 153), };

	private enum STATE {
		NEW, STARTED, DONE
	};

	private static STATE currState = STATE.NEW;

	public KidWindow() {
		super();
		
		monitor = GraphicsEnvironment.getLocalGraphicsEnvironment()
				.getDefaultScreenDevice();

		createBoard();
		
		if (monitor.isFullScreenSupported()) 
			monitor.setFullScreenWindow(this);
		addMouseListener(this);
	}

	private void newGame() {
		currState = STATE.NEW;
		createBoard();
		repaint();
	}
	
	int clickedCount = 0;
	public void mouseClicked(MouseEvent e) {
		System.out.println(currState);
		if (currState == STATE.DONE) {
			newGame();
			return;
		}
		
		int x = e.getX();
		int y = e.getY();
		
		for (BoardItem item : board) {
			if (item.matched)
				continue; 

			if (x >= item.x && x <= item.x + SIZE &&
				y >= item.y && y <= item.y + SIZE) {
				if (item.clicked) {
					clickedCount--;
					item.clicked = false;
				} else {
					item.clicked = true;
					
					if (clickedCount == 1) {
						clickedCount = 0;
						if (checkMatches()) {
							if (checkFinish()) {
								currState = STATE.DONE;
								if (SIZE > 50)
									SIZE = SIZE - 50;
								else 
									SIZE = 20;
							}
						}
							
						continue;
					} 
					
					clickedCount++;					
				}
			}
		}
		
		repaint();
	}
	
	public boolean checkFinish() {
		for (BoardItem item : board) {
			if (!item.matched)
				return false;
		}
		return true;
	}
	
	public boolean checkMatches() {
		List<BoardItem> list = new ArrayList<BoardItem>();
		for (BoardItem item : board) {
			if (item.clicked) {
				list.add(item);
				item.clicked = false;
			}
		}
		
		boolean matched = false;
		Color c = null;
		for (BoardItem item : list) {
			if (c == null)
				c = item.color;
			else if (item.color == c)
				matched = true;
		}

		if (matched)
			for (BoardItem item : list) 
				item.matched = true;
		
		return matched;
	}
	

	class BoardItem {
		int x;
		int y;
		Color color;
		boolean clicked;
		boolean matched;
	}
	
	private BoardItem[] board = new BoardItem[16];
	private void createBoard() {
		final int padding = 10;
		final int rowscols = 4;
		int startx = (monitor.getDisplayMode().getWidth() - (SIZE * rowscols + (padding * rowscols))) / 2;
		int starty = (monitor.getDisplayMode().getHeight() - (SIZE * rowscols + (padding * rowscols))) / 2;
		int itemCount = 0;
		for (int i = startx; i < startx + padding + SIZE * rowscols; i = i + SIZE
				+ padding) {
			for (int j = starty; j < starty + padding + SIZE * rowscols; j = j
					+ SIZE + padding) {
				BoardItem item = new BoardItem();
				item.color = getUnusedColor();
				item.clicked = false;
				item.matched = false;
				item.x = i;
				item.y = j;
				board[itemCount] = item;
				itemCount++;
			}
		}
		usedMap = null;
	}
	
	private void drawBoard() {
		createBufferStrategy(2);
		Graphics g = getBufferStrategy().getDrawGraphics();
		
		g.setColor(Color.BLACK);
		g.fillRect(0, 0, monitor.getDisplayMode().getWidth(), monitor
				.getDisplayMode().getHeight());

		for (BoardItem item : board) {
			if (item.matched)
				g.setColor(Color.BLACK);
			else if (item.clicked)
				g.setColor(Color.WHITE);
			else 
				g.setColor(item.color);
			g.fillRoundRect(item.x, item.y, SIZE, SIZE, 2, 2);
		}
		
		g.dispose();
		getBufferStrategy().show();
		currState = STATE.STARTED;
	}
	
	private void drawFinish() {
		createBufferStrategy(2);
		Graphics g = getBufferStrategy().getDrawGraphics();
		
		g.setColor(Color.BLACK);
		g.fillRect(0, 0, monitor.getDisplayMode().getWidth(), monitor
				.getDisplayMode().getHeight());

		g.setColor(Color.GREEN);
		
		g.setFont(new Font("TimesRoman", Font.PLAIN,  44));
		g.drawString("GOOD JOB!", 100, 100);
		
		g.dispose();
		getBufferStrategy().show();
	}
	
	public void paint(Graphics g) {
		if (currState == STATE.NEW || currState == STATE.STARTED) 
			drawBoard();

		else if (currState == STATE.DONE)
			drawFinish();
	}

	HashMap<Integer, Integer> usedMap = null;
	public Color getUnusedColor() {
		if (usedMap == null)
			usedMap = new HashMap<Integer, Integer>();

		Random r = new Random();
		boolean used = true;
		int index;
		do {

			index = r.nextInt(8);
			if (usedMap.get(index) == null) {
				usedMap.put(index, 1);
				used = false;
			} else if (usedMap.get(index) == 1) {
				usedMap.put(index, 2);
				used = false;
			}
		} while (used);

		return colors[index];
	}

	public void close() {
		monitor.setFullScreenWindow(null);
	}

	public void mouseEntered(MouseEvent arg0) {
		// TODO Auto-generated method stub

	}

	public void mouseExited(MouseEvent arg0) {
		// TODO Auto-generated method stub

	}

	public void mousePressed(MouseEvent arg0) {
		// TODO Auto-generated method stub

	}

	public void mouseReleased(MouseEvent arg0) {
		// TODO Auto-generated method stub

	}
}

