package szakdolgozat.client.game;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

import szakdolgozat.client.ui.GameDialog;
import szakdolgozat.shared.User;

import com.google.gwt.widgetideas.graphics.client.Color;

public class Game {

	public User opponent;
	private final int TABLE_SIZE = 20;
	private final int GREEN_PLAYER = 1; // 1.
	private final int BLUE_PLAYER = -1; // 2.
	private int currentPlayer = GREEN_PLAYER;
	private Set<Point> selectedNodes;
	private ArrayList<Line> greenPlayerLines;
	private ArrayList<Line> bluePlayerLines;	

	public ArrayList<Line> getCurrentPlayerLines() {
		return currentPlayer == GREEN_PLAYER ? greenPlayerLines
				: bluePlayerLines;
	}

	public ArrayList<Line> getOpponentCurrentPlayerLines() {
		return currentPlayer == BLUE_PLAYER ? greenPlayerLines
				: bluePlayerLines;
	}

	public void addToCurrentPlayerLines(Line line) {
		if (currentPlayer == GREEN_PLAYER)
			greenPlayerLines.add(line);
		else
			bluePlayerLines.add(line);
	}

	private int[][] gameTable = new int[TABLE_SIZE][TABLE_SIZE];

	public Game() {
		for (int i = 0; i < TABLE_SIZE; i++) {
			for (int j = 0; j < TABLE_SIZE; j++) {
				gameTable[i][j] = 0;
			}
		}
		greenPlayerLines = new ArrayList<Line>();
		bluePlayerLines = new ArrayList<Line>();		
		selectedNodes = new HashSet<Point>();
	}

	public void nodeSelected(int row, int col, int positionInBrowserX,
			int positionInBrowserY) {
		gameTable[row][col] = currentPlayer;
		GameDialog.lineCanvas
				.setFillStyle(currentPlayer == GREEN_PLAYER ? Color.GREEN
						: Color.BLUE);
		GameDialog.lineCanvas.fillRect(positionInBrowserX - 5,
				positionInBrowserY - 6, 13, 13);
		Point nodeSelected = new Point(row, col, positionInBrowserX,
				positionInBrowserY);

		drawNewLines(nodeSelected);
		switchPlayers();
		selectedNodes.add(nodeSelected);
	}

	private void drawNewLines(Point lastSelectedNode) {
		// System.err.println("őt választottam ki utoljára: " +
		// lastSelectedNode);
		for (Point point : selectedNodes) {
			// System.err.println("\t ővele hasonlítom össze: " + point);
			if (isInGoodPositionFor(lastSelectedNode, point)) {
				// System.err.println("\t\t lólépésben van");
				if (gameTable[(int) lastSelectedNode.getX()][(int) lastSelectedNode
						.getY()] == gameTable[(int) point.getX()][(int) point
						.getY()]) {
					// System.err.println("\t\t\t\t ugyan az a játékos lépte ("
					// + currentPlayer + ")");
					Line line = new Line(lastSelectedNode, point);
					// System.err.println("\t\t\t\t szép új vonalacskám: " +
					// line);
					boolean draw = true;
					if (!getCurrentPlayerLines().contains(line)) {
						// System.err
						// .println("\t\t\t\t\t még nem szerepel a vonalai között");
						for (Line l : getOpponentCurrentPlayerLines()) {
							// System.err.println("\t\t\t\t\t ő vele hasonlítom: "
							// + l);
							if (l.lineSegmentIntersection(line)) {
								// System.err
								// .println("\t\t\t\t\t\t\t metszi egy ellenfél vonalát, nem rajzoljuk");
								draw = false;
								break;
							}
						}
					}
					if (draw) {
						// System.err.println("éljen vonalat húzunk!");
						addToCurrentPlayerLines(line);
						GameDialog.lineCanvas
								.setStrokeStyle(currentPlayer == GREEN_PLAYER ? Color.GREEN
										: Color.BLUE);
						GameDialog.lineCanvas.beginPath();
						GameDialog.lineCanvas.moveTo(line.getP1()
								.getPositionInBrowserX(), line.getP1()
								.getPositionInBrowserY());
						GameDialog.lineCanvas.lineTo(line.getP2()
								.getPositionInBrowserX(), line.getP2()
								.getPositionInBrowserY());
						GameDialog.lineCanvas.closePath();
						GameDialog.lineCanvas.stroke();
					}
				}
			}
		}
	}

	private boolean isInGoodPositionFor(Point point1, Point point2) {
		double i1 = point1.getX(), i2 = point2.getX(), j1 = point1.getY(), j2 = point2
				.getY();
		if (((i1 + 1 == i2 && j1 + 2 == j2) || (i1 + 2 == i2 && j1 + 1 == j2)
				|| (i1 + 2 == i2 && j1 - 1 == j2)
				|| (i1 + 1 == i2 && j1 - 2 == j2)
				|| (i1 - 1 == i2 && j1 - 2 == j2)
				|| (i1 - 2 == i2 && j1 - 1 == j2)
				|| (i1 - 2 == i2 && j1 + 1 == j2) || (i1 - 1 == i2 && j1 + 2 == j2))) {
			return true;
		}
		return false;
	}

	private void switchPlayers() {
		currentPlayer *= -1;
	}

	public boolean isNodeSelectable(int row, int col) {
		if (gameTable[row][col] != 0) {
			return false;
		}

		if (((row == 0 || row == TABLE_SIZE - 1) && (col != 0 && col != TABLE_SIZE - 1))
				&& currentPlayer == BLUE_PLAYER) {
			return false;
		}

		if (((col == 0 || col == TABLE_SIZE - 1) && (row != 0 && row != TABLE_SIZE - 1))
				&& currentPlayer == GREEN_PLAYER) {
			return false;
		}

		return true;
	}

	public boolean isGameEndState() {
		if (isGreenBasesSelected())
			for (Line line : greenPlayerLines) {
				if (line.getP1().getX() == 0) {
					return findWay(greenPlayerLines, line.getP1(),
							GREEN_PLAYER);					
				} else if (line.getP2().getX() == 0) {
					return findWay(greenPlayerLines, line.getP2(),
							GREEN_PLAYER);					
				}
			}
		if (isBlueBasesSelected())
			for (Line line : bluePlayerLines) {
				if (line.getP1().getY() == 0) {
					return findWay(bluePlayerLines, line.getP1(), BLUE_PLAYER);
				} else if (line.getP2().getY() == 0) {
					return findWay(bluePlayerLines, line.getP2(), BLUE_PLAYER);
				}
			}
		return false;
	}

	private boolean findWay(ArrayList<Line> userlines, Point currentEndPoint,
			int player) {

		if (currentEndPoint.getX() == TABLE_SIZE - 1 && player == GREEN_PLAYER) {
			return true;
		} else if (currentEndPoint.getY() == TABLE_SIZE - 1
				&& player == BLUE_PLAYER) {
			return true;
		}

		if (userlines.size() == 0)
			return false;

		ArrayList<Line> lines = new ArrayList<Line>();
		lines.addAll(userlines);

		for (Line line : lines) {
			if (line.getP1().equals(currentEndPoint)) {
				userlines.remove(line);
				boolean result = findWay(userlines, line.getP2(), player);
				if (result == true)
					return true;
			} else if (line.getP2().equals(currentEndPoint)) {
				userlines.remove(line);
				boolean result = findWay(userlines, line.getP1(), player);
				if (result == true)
					return true;
			}
		}

		return false;
	}

	private boolean isBlueBasesSelected() {
		int i, j;
		for (i = 0; i < TABLE_SIZE; i++) {
			if (gameTable[i][0] < 0) {
				for (j = 0; j < TABLE_SIZE; j++) {
					if (gameTable[j][TABLE_SIZE - 1] < 0) {
						return true;
					}
				}
				if (j == TABLE_SIZE)
					return false;
			}
		}

		return false;
	}

	private boolean isGreenBasesSelected() {
		int i, j;
		for (i = 0; i < TABLE_SIZE; i++) {
			if (gameTable[0][i] > 0) {
				for (j = 0; j < TABLE_SIZE; j++) {
					if (gameTable[TABLE_SIZE - 1][j] > 0) {
						return true;
					}
				}
				if (j == TABLE_SIZE)
					return false;
			}
		}

		return false;
	}
}
