package lab00;

import java.awt.GridLayout;

import javax.swing.JFrame;
import javax.swing.JPanel;


public class TicTacToe extends JFrame implements Runnable {
	private Line[] lines;
	private static final long serialVersionUID = 1L;
	
	public TicTacToe() {
		super("Tic-Tac-Toe");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setContentPane(new JPanel(new GridLayout(3,3,5,5)));
		// The board consists of a grid of 9 buttons
		// Define all 8 sets of winning lines
		lines=new Line[8];
		for(int l=0;l<8;l++) lines[l]=new Line(this);
		for(int r=0;r<3;r++) {
			for(int c=0;c<3;c++) {
				Square sq = new Square(this);
				getContentPane().add(sq);
				lines[r].add(sq);
				lines[c+3].add(sq);
				if (r==c) lines[6].add(sq);
				if ((r==0 && c==2) || (r==1 && c==1) || (r==2 && c==0) ) lines[7].add(sq);
			}
		}
	}
	
	public boolean checkWinner() {
		for(Line l : lines) if (l.isWinner()) return true;	
		return false;
	}
	
	public void disableAllSquares() {
		for(int i=0;i<3;i++) lines[i].disableAllSquares();
	}
	
	public void computerTurn() {
		if (!chooseWinner()) {
			if (!blockOpponent()) {
				if (!chooseFork()) {
					if (!blockFork()) {
					// nextOpen();
						bestOpen();
					}
				}
				
			}
		}
	}
	

	
	private boolean chooseWinner() { // Choose a winner if there is one
		for(Line l : lines) {
			Square sq=l.allButOne("O");
			if (sq!=null) {
				sq.choose("O");
				checkWinner();
				return true;
			}
		}
		return false;
	}
	
	private boolean blockOpponent() { // Block opponent if need be
		for(Line l : lines) {
			Square sq=l.allButOne("X");
			if (sq!=null) {
				sq.choose("O");
				return true;
			}
		}
		return false;
	}
	
	private void nextOpen() { // Choose the next open slot
		for (Line l : lines) {
			Square sq = l.avail();
			if (sq!=null) {
				sq.choose("O");
				return;
			}
		}
	}
	
	private void bestOpen() { // Choose the best open slot...
		// Center first
		Square center = lines[7].getSquare(1);
		if (center.getText().equals(" ")) {
			center.choose("O");
			return;
		}
		// Anything on diagonals next
		Square corner = lines[6].avail();
		if (corner!=null) {
			corner.choose("O");
			return;
		}
		corner=lines[7].avail();
		if (corner!=null) {
			corner.choose("O");
			return;
		}
		nextOpen();
	}
	
	private boolean chooseFork() {
		for(Line l : lines) {
			for (Line fl : lines) {
				if (l==fl) continue;
				Square common=l.getFork(fl,"O");
				if (common!=null) {
					common.choose("O");
					return true;
				}
			}
		}
		return false;
	}
	
	private boolean blockFork() {
		int numBlocks=0;
		Square[] blocks = new Square[9];
		for(Line l : lines) {
			for (Line fl : lines) {
				if (l==fl) continue;
				Square common=l.getFork(fl,"X");
				if (common!=null) {
					boolean there=false;
					for(int i=0;i<numBlocks;i++) {
						if (blocks[i]==common) there=true; 
					}
					if (!there) {
						blocks[numBlocks]=common;
						numBlocks++;
					}
				}
			}
		}
		if (numBlocks==1) {
			blocks[0].choose("O");
			return true;
		} else if (numBlocks>1) {
			// Need to force a square that is not a block
			// System.out.println("Weird case!");
			for(Line l : lines) {
				if (l.onlyOne("O")) {
					Square nb = null;
					for(int i=0;i<3;i++) {
						Square sq = l.getSquare(i);
						if (sq.getText().equals("O")) continue;
						boolean isBlocked=false;
						for(int j=0;j<numBlocks; j++) {
							if (sq==blocks[j]) isBlocked=true;
						}
						if (!isBlocked) nb=sq;
					}
					if (nb!=null) {
						for(int i=0;i<3;i++) {
							Square sq = l.getSquare(i);
							if (!sq.getText().equals(" ")) continue;
							if(sq==nb) continue;
							sq.choose("O");
							return true;
						}
					}
				}
			}
			
		}
		return false;
	}
	
	@Override
	public void run() {
		pack();
		setVisible(true);		
	}
	
	public static void main(String[] args) {
		//Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new TicTacToe());
	}

	
}
