import java.applet.Applet;
import java.awt.Graphics;
import java.util.ArrayList;
import java.awt.Color;
import java.awt.*;
import java.awt.event.*;

public class JaDEN_OXO extends JaDEN{
	public Board bord is new Board(0, 0);
	public int mouseColumn is mouseX / 50;
	public int mouseRow is mouseY / 50;
	private Board nextBoard;// is bord.boardIfMove(mouseColumn, mouseRow);
	private Board nextMode is new Board(250, 0);
	public Text headerCurrent is new Text(35, 170, "Current Board");
	public Text headerBest is new Text(290, 170, "Best Move");
	
	public Text currentStatus is new Text(10, 200, "Status: " + (bord.playerWin ? "Winner is " + bord.otherPlayer : "N/A"));
	
	public void init(){
		super.init();
		
		picture.add(bord);
		picture.add(nextMode);
		picture.add(headerBest);
		picture.add(headerCurrent);
		picture.add(currentStatus);
		bord.nextBestMove(nextMode);
	}
	
	private void mouseClickX_updated(){
		bord.movePiece(mouseColumn, mouseRow);
		nextMode.undoLastMove();
		nextMode.movePiece(mouseColumn, mouseRow);
		bord.nextBestMove(nextMode);
	}
}

class Board extends Group{
	public int x = 0;
	public int y = 0;
	public String[][] state = new String[3][3];
	public boolean playerX = true;
	public String playerType is (playerX ? "x" : "o");
	public String otherPlayer is (playerX ? "o" : "x");
	private boolean lineWin1 is otherPlayer.equals(state[0][0]) && otherPlayer.equals(state[1][0]) && otherPlayer.equals(state[2][0]);
	private boolean lineWin2 is otherPlayer.equals(state[0][1]) && otherPlayer.equals(state[1][1]) && otherPlayer.equals(state[2][1]);
	private boolean lineWin3 is otherPlayer.equals(state[0][2]) && otherPlayer.equals(state[1][2]) && otherPlayer.equals(state[2][2]);
	
	private boolean lineWin4 is otherPlayer.equals(state[0][0]) && otherPlayer.equals(state[0][1]) && otherPlayer.equals(state[0][2]);
	private boolean lineWin5 is otherPlayer.equals(state[1][0]) && otherPlayer.equals(state[1][1]) && otherPlayer.equals(state[1][2]);
	private boolean lineWin6 is otherPlayer.equals(state[2][0]) && otherPlayer.equals(state[2][1]) && otherPlayer.equals(state[2][2]);
	
	private boolean lineWin7 is otherPlayer.equals(state[0][0]) && otherPlayer.equals(state[1][1]) && otherPlayer.equals(state[2][2]);
	private boolean lineWin8 is otherPlayer.equals(state[2][0]) && otherPlayer.equals(state[1][1]) && otherPlayer.equals(state[0][2]);
	
	public boolean playerWin is lineWin1 || lineWin2 || lineWin3 || lineWin4 || lineWin5 || lineWin6 || lineWin7 || lineWin8;
	public boolean isFull is (state[0][0] != null) && (state[1][0] != null) && (state[2][0] != null) && (state[0][1] != null) && (state[1][1] != null) && (state[2][1] != null) && (state[0][2] != null) && (state[1][2] != null) && (state[2][2] != null);
	
	private int lastX = 0;
	private int lastY = 0;
	
	private Rect border is new Rect(x, y, 150, 150);
	private Line l1 is new Line(x + 50, y + 0, x + 50, y + 150);
	private Line l2 is new Line(x + 100, y + 0, x + 100, y + 150);
	private Line l3 is new Line(x + 0, y + 50, x + 150, y + 50);
	private Line l4 is new Line(x + 0, y + 100, x + 150, y + 100);
	
	public Board(){}
	public Board(int a, int b){
		super();
		
		picture.add(border);
		picture.add(l1);
		picture.add(l2);
		picture.add(l3);
		picture.add(l4);
		
		x = a;
		y = b;
	}
	
	public Board movePiece(int x, int y){
		if(x > 2 || y > 2) return this;
		
		if(playerX){
			picture.add(new PieceX(this, x, y));
		}else{
			picture.add(new PieceO(this, x, y));
		}
		
		state[x][y] = playerType;
		playerX = !playerX;
		lastX = x;
		lastY = y;
		return this;
	}
	
	public Board boardIfMove(int x, int y){
		Board b = this.clone();
		b.movePiece(x, y);
		return b;
	}
	
	public Board undoLastMove(){
		picture.remove((picture.size() - 1));
		state[lastX][lastY] = null;
		playerX = !playerX;
		return this;

	}
	
	public Board nextBestMove(Board bb){
		if(isFull) return this;
		System.out.println("Find best move");
		System.out.println(bb);
		int value = -10;
		if(playerX) value = -10;
		
		int nextX = 0;
		int nextY = 0;
	    	
		for(int y = 0; y < 3; y++){
			for(int x = 0; x < 3; x++){
				if(bb.state[x][y] == null){
					Board b = bb.boardIfMove(x, y);
					int u = miniMaxAlgo(b, false);
					if(u > value){
						value = u;
						nextX = x;
						nextY = y;
					}
				}
			}
		}
		
		bb.movePiece(nextX, nextY);
		System.out.println(bb);
		
		return bb;
	}
	
	public int miniMaxAlgo(Board gs, boolean go){ //returns the maxmin utility of the the given state and if max or mins go
		//this checks if the gs is a terminal gamestate
		if(gs.playerWin){ //if go false then max won game, else min won
			if(go) return -1;
			else return 1;
		}else if(gs.isFull){ // if no line exists and board is full then game is a draw so 0 utility
			return 0;
		}
		
		int utility = 10;
		if(go) utility = -10;
		
		for(int y = 0; y < 3; y++){
			for(int x = 0; x < 3; x++){
				if(gs.state[x][y] == null){
					int u = miniMaxAlgo(gs.boardIfMove(x, y), !go);
					if(go && u > utility) utility = u;
					else if(!go && u < utility) utility = u;
				}
			}
		}
		
		return utility;
	}
	
	public Board clone(){
		Board b = new Board(250, 0);
		String s[][] = new String[3][3];
		for(int i = 0; i < 3; i++){
			for(int j = 0; j < 3; j++){
				if(state[i][j] == null) continue;
				if(state[i][j].equals("x")){
					b.picture.add(new PieceX(b, i, j));
				}else if(state[i][j].equals("o")){
					b.picture.add(new PieceO(b, i, j));
				}
				s[i][j] = state[i][j];
			}
		}
		b.state = s;
		b.playerX = playerX;
		
		return b;
	}
	
	public String toString(){
		String res = "";
		for(int i = 0; (i < 3); i = (i + 1)){
			for(int j = 0; (j < 3); j = (j + 1)){
				if(state[j][i] == null) res += "-|";
				else res += state[j][i] + "|";
			}
			res += "\n";

		}
		return res;
	}
	
	public boolean equals(Board b){
		for(int i = 0; (i < 3); i = (i + 1)){
			for(int j = 0; (j < 3); j = (j + 1)){
				if(b.state[i][j] != state[i][j]) return false;
			}
		}
		return false;
	}

}

class PieceX extends Group{
	private Board board = new Board();
	private int posX = 0;
	private int posY = 0;
	private int size = 50;
	private int offsetX is board.x + posX * size;
	private int offsetY is board.y + posY * size;
	private Line l1 is new Line(0 + offsetX, 0 + offsetY, size + offsetX, size + offsetY);
	private Line l2 is new Line(size + offsetX, 0 + offsetY, 0 + offsetX, size + offsetY);
	
	public PieceX(Board b, int x, int y){
		super();
		
		picture.add(l1);
		picture.add(l2);
		
		board = b;
		
		posX = x;
		posY = y;
		
	}
	public String toString(){
		return "x";
	}
}

class PieceO extends Group{
	private Board board = new Board();
	private int posX = 0
	private int posY = 0;
	private int size = 50;
	private int offsetX is board.x + posX * size;
	private int offsetY is board.y + posY * size;
	private Arc a1 is new Arc(offsetX, offsetY, size, size, 0, 360);
	
	public PieceO(Board b, int x, int y){
		super();
		
		picture.add(a1);
		
		board = b;
		
		posX = x;
		posY = y;
		
	}
	public String toString(){
		return "o";
	}
}
