import java.util.Random;

/**
 * Separamos en esta clase todo lo que no tenga nada que ver con la tecnología.
 * Así será más facil llevarlo en el futuro a otra implementación cualquiera.
 * 
 * @author luis
 * 
 */
public class Modelo {

	public final static int NUM_CUADROS = 8;

	public final static int VACIO = 0;
	
	public final static int HOMBRE = 1;
	public final static int HOMBRE_GANADORA = 2;	
	public final static int MAQUINA = 3;
	public final static int MAQUINA_GANADORA=4;


	private final static int UNO = 2; // A efectos de valoración
	private final static int CUATRO = UNO * 4096;

	private static int tablero[][] = new int[NUM_CUADROS][NUM_CUADROS];

	Random rand = new Random();

	public void addHombre(int x) {
		tablero[x][libre(x)] = HOMBRE;
	}

	public void addMaquina(int x, int y) {
		tablero[x][libre(x)] = MAQUINA;
	}

	public int get(int x, int y) {
		return tablero[x][y];
	}

	boolean hayLibre(int x) {
		return libre(x) < NUM_CUADROS;
	}
	
	void limpiar() {
		for(int i=0; i<NUM_CUADROS; i++) {
			for(int j=0; j<NUM_CUADROS; j++) {
				tablero[i][j]=VACIO;
			}
		}
	}
	
	int libre(int x) {
		int i;
		for (i = 0; i < NUM_CUADROS && tablero[x][i] != VACIO; i++)
			;
		return (i);
	}

	int valorar4(int x[], int y[]) {
		int i;
		int hombres = 0, maquinas = 0;
		for (i = 0; i < 4; i++) {
			switch (tablero[x[i]][y[i]]) {
			case HOMBRE:
				++hombres;
				break;
			case MAQUINA:
				++maquinas;
				break;
			}
		}
		if (hombres == 0) {
			if (maquinas == 3)
				return (UNO * 32);
			if (maquinas == 2)
				return (UNO * 8);
			if (maquinas == 1)
				return (UNO * 1);
		}
		if (maquinas == 0) {
			if (hombres == 3)
				return (-UNO * 128);
			if (hombres == 2)
				return (-UNO * 16);
			if (hombres == 1)
				return (-UNO * 2);
		}
		if (hombres == 4)
			return (-CUATRO);
		if (maquinas == 4)
			return (CUATRO);
		return (0);
	}

	int valorar() {
		int s[] = new int[3];
		int x[] = new int[4];
		int y[] = new int[4];

		int i, j, k;
		int v = 0, v1;
		for (i = 0; i < NUM_CUADROS; i++)
			for (j = 0; j <= NUM_CUADROS - 4; j++) {
				for (k = 0; k < 4; k++) {
					x[k] = i;
					y[k] = j + k;
				}
				v1 = valorar4(x, y);
				if (labs(v1) == CUATRO) {
					return (v1);
				}
				v += (v1 / 2L);
				if (i < NUM_CUADROS - 3) {
					for (k = 0; k < 4; k++) {
						x[k] = i + k;
						y[k] = j + k;
					}
					v1 = valorar4(x, y);
					if (labs(v1) == CUATRO)
						return (v1);
					v += v1;
				}
				if (i > 2) {
					for (k = 0; k < 4; k++) {
						x[k] = i - k;
						y[k] = j + k;
					}
					v1 = valorar4(x, y);
					if (labs(v1) == CUATRO)
						return (v1);
					v += v1;
				}
			}
		for (j = 0; j < NUM_CUADROS; j++)
			for (i = 0; i <= NUM_CUADROS - 4; i++) {
				for (k = 0; k < 4; k++) {
					x[k] = i + k;
					y[k] = j;
				}
				v1 = valorar4(x, y);
				if (labs(v1) == CUATRO)
					return (v1);
				v += (v1 / 2L);
			}
		return (v);
	}

	boolean cuatroEnRaya() {
		int s[] = new int[3];
		int x[] = new int[4];
		int y[] = new int[4];
		int i, j, k;
		int v;
		for (i = 0; i < NUM_CUADROS; i++)
			for (j = 0; j <= NUM_CUADROS - 4; j++) {
				for (k = 0; k < 4; k++) {
					x[k] = i;
					y[k] = j + k;
				}
				v = labs(valorar4(x, y));
				if (v == CUATRO) {
					ponerBlink(x, y);
					return (true);
				}
				if (i < NUM_CUADROS - 3) {
					for (k = 0; k < 4; k++) {
						x[k] = i + k;
						y[k] = j + k;
					}
					v = labs(valorar4(x, y));
					if (v == CUATRO) {
						ponerBlink(x, y);
						return (true);
					}
				}
				if (i > 2) {
					for (k = 0; k < 4; k++) {
						x[k] = i - k;
						y[k] = j + k;
					}
					v = labs(valorar4(x, y));
					if (v == CUATRO) {
						ponerBlink(x, y);
						return (true);
					}
				}
			}
		for (j = 0; j < NUM_CUADROS; j++)
			for (i = 0; i <= NUM_CUADROS - 4; i++) {
				for (k = 0; k < 4; k++) {
					x[k] = i + k;
					y[k] = j;
				}
				v = labs(valorar4(x, y));
				if (v == CUATRO) {
					ponerBlink(x, y);
					return (true);
				}
			}
		return false;
	}

	void ponerBlink(int x[], int y[]) {
		int i;
		for (i = 0; i < 4; i++)
			poner(++(tablero[x[i]][y[i]]), x[i], y[i]);
	}

	void poner(int tipo, int x, int y) {
		tablero[x][y] = tipo;
	}

	private int labs(int x) {
		return Math.abs(x);
	}

	int JuegaMaquina() {
		int x, y, mx = -1, my = 0;
		int xj, yj;
		int valor = -Integer.MAX_VALUE, v;
		int valorj;

		for (x = 0; x < NUM_CUADROS; x++)
			if ((y = libre(x)) < NUM_CUADROS) {
				tablero[x][y] = MAQUINA;
				v = valorar();
				if (v == CUATRO) {
					valor = v;
					mx = x;
					my = y;
					break;
				}
				valorj = Integer.MAX_VALUE;
				for (xj = 0; xj < NUM_CUADROS; xj++)
					if ((yj = libre(xj)) < NUM_CUADROS) {
						tablero[xj][yj] = HOMBRE;
						v = valorar();
						if (v < valorj)
							valorj = v;
						tablero[xj][yj] = VACIO;
						if (v < valor)
							break;
					}
				if (valorj > valor
						|| (valorj == valor && (rand.nextInt(2)) == 1)) {
					valor = valorj;
					mx = x;
					my = y;
				}
				tablero[x][y] = VACIO;
			}
		poner(MAQUINA, mx, my);
		return mx;
	}

}

