// Student: R. S.
// Student: C. W.
// MineSweeper Project
// Computer Science 1

// Implementation of the Mine Sweeper game. 
//
// Single-click toggles a flag, double-click reveals the cell.

package edu.compsci;

import cs1.android.*;

import java.util.Random;

public class MineSweeperApp extends AndroidApp 
{
	//constants used throughout the program

	final int height = 480;  // 320x480 device
	final int width = 320;   //

	//size left at top of board for smiley face
	final int SMILEY = 120;
	//indicates which cells have already been opened
	final int MARKED = 11;
	//indicates an empty cell
	final int EMPTY = 10;
	//the pixel size of the cell images including the numbers and mines
	final int IMAGESIZE = 36;
	//the number of rows on the board
	final int ROW = (height - 120)/ IMAGESIZE;
	//the number of columns on the board
	final int COL = width / IMAGESIZE;
	//indicates a mine
	final int MINE = 9;
	//the probability that a mine is found at a particular cell
	final double PROBABILITY = .2;

	//method used to draw images in the cells
	void drawImage1(int r, int c, String filename)
	{
		canvas.drawImage(20 + c*IMAGESIZE, 20 + r*IMAGESIZE + SMILEY, filename);
	}

	//method used to draw the smiley faces
	void drawImage2(String filename)
	{
		canvas.drawImage(width/2, SMILEY/2, filename);
	}

	//called when mouse is clicked: x, y, are the mouse coordinates,
	//left/right indicate which button pressed
	//    public void mouseClicked(int x, int y, boolean left, boolean right)

	//handle the touch interaction between diffrent players
	void playMineSweeper()
	{
		canvas.setBackground("white");
		boolean gameOver = false;
		int correct = 0;

		int[][] field = placeMines(ROW, COL);
		updateField(field);
		drawField(field);

		while (gameOver == false)
		{
			/*
			 * New code for Android App
			 */
			Touch touch = canvas.waitForTouch();
			int x = (int) touch.getX();
			int y = (int) touch.getY();
			int taps = touch.getTaps();
			boolean left = taps == 2;
			boolean right = !left;
			/*
			 * End New code for Android App
			 */

			int r = (y - SMILEY)/IMAGESIZE;

			int c = x/IMAGESIZE;

			if(left == true && field[r][c] != MINE)
			{
				drawImage2("winky.png");
				//FIX canvas.sleep(.2);
				drawImage2("smiley.png");
				revealCells(field, r, c);
				correct = correct + 1;
			}
			else if(right == true && field[r][c] > 0 && field[r][c] != MARKED)
			{
				drawImage1(r, c, "flag.png");
				field[r][c] = -1*field[r][c];

				if(field[r][c] == MINE)
				{
					correct = correct + 1;
				}
			}
			else if(right == true && field[r][c] < 0)
			{
				drawImage1(r, c, "empty.png");
				field[r][c] = -1*field[r][c];

				if(field[r][c] == MINE)
				{
					correct = correct - 1;
				}
			}
			else if(left == true && field[r][c] == MINE)
			{
				drawImage2("sad.png");
				canvas.drawSquare(20 + c*IMAGESIZE, 20 + r*IMAGESIZE + SMILEY, IMAGESIZE, "red");
				revealMines(field);
				gameOver = true;
			}
			else if(correct == ROW * COL)
			{
				gameOver = true;
			}
		}
	}

	//draws a table of empty squares with same proportions as given field
	void drawField(int[][] field)
	{
		drawImage2("smiley.png");

		for(int r = 0; r < field.length; r = r + 1)
		{
			for(int c = 0; c < field[0].length; c = c + 1)
			{
				drawImage1(r, c, "empty.png");
			}
		}
	}

	//generates a random integer
	int randomInteger(int low, int high)
	{
		int number = new Random().nextInt(high-low);
		number = number + low;
		return number;
	}

	//generates a table and places mines (designated by 9) in a cell with probability of 20%
	int[][] placeMines(int rows, int cols)
	{
		int[][] result = new int[rows][cols];

		for(int mines = 0; mines < rows*cols*PROBABILITY; mines = mines + 1)
		{
			int r = randomInteger(0, rows - 1);
			int c = randomInteger(0, cols - 1);
			result[r][c] = MINE;
		}

		return result;
	}

	//determines if a cell on the given table is valid
	boolean isValid(int[][] board, int r, int c)
	{
		if(r >= 0 && r < board.length && c >= 0 && c < board[r].length)
		{
			return true;
		}
		else
		{
			return false;
		}
	}

	//updates field so cells count how many mines are connected to them
	void updateField(int[][] field)
	{
		for(int r = 0; r < field.length; r = r + 1)
		{
			for(int c = 0; c < field[r].length; c = c + 1)
			{
				int num = 0;

				if(field[r][c] != MINE)
				{
					if(isValid(field, r - 1, c) && field[r - 1][c] == MINE)
					{
						num = num + 1;
					}
					if(isValid(field, r - 1, c + 1) && field[r - 1][c + 1] == MINE)
					{
						num = num + 1;
					}
					if(isValid(field, r, c + 1) && field[r][c + 1] == MINE)
					{
						num = num + 1;
					}
					if(isValid(field, r + 1, c + 1) && field[r + 1][c + 1] == MINE)
					{
						num = num + 1;
					}
					if(isValid(field, r + 1, c) && field[r + 1][c] == MINE)
					{
						num = num + 1;
					}
					if(isValid(field, r + 1, c - 1) && field[r + 1][c - 1] == MINE)
					{
						num = num + 1;
					}
					if(isValid(field, r, c - 1) && field[r][c - 1] == MINE)
					{
						num = num + 1;
					}
					if(isValid(field, r - 1, c - 1) && field[r - 1][c - 1] == MINE)
					{
						num = num + 1;
					}
					if(num == 0)
					{
						field[r][c] = EMPTY;
					}
					else
					{
						field[r][c] = num;
					}
				}
			}
		}
	}

	//prints the image of the numbered cell given the row and column
	void drawNum(int[][] field, int row, int col)
	{
		if(field[row][col] == EMPTY)
		{
			drawImage1(row, col, "m0.png");
		}

		for(int i = 1; i <= 8; i = i + 1)
		{
			if(field[row][col] == i)
			{
				drawImage1(row, col, "m"+i+".png");
			}
		}
	}

	//given the row and column of a field, reveals selected numbered cell if 
	//the number in the cell is greater than 0, and the selected numbered cell
	//in addition to the surrounding 8 numbered cell if the number of selected
	//cell is 0
	void revealCells(int[][] field, int row, int col)
	{
		if(isValid(field, row, col) && field[row][col] != MARKED)
		{
			if(field[row][col] == EMPTY)
			{
				drawImage1(row, col, "m0.png");
				field[row][col] = MARKED;

				int[] dr = {-1,-1,-1,0,0,1,1,1};
				int[] dc = {-1,0,1,-1,1,-1,0,1};

				for(int i=0;i < 8;i=i+1)
				{
					int newR= row+dr[i];
					int newC= col+dc[i];

					if(isValid(field, newR, newC))
					{
						revealCells(field, newR, newC);
					}
				}
			}
			else
			{
				drawNum(field, row, col);
				field[row][col] = MARKED;
			}
		}
	}

	//reveals all the mines in a given field
	void revealMines(int[][] field)
	{
		for(int r=0;r<field.length;r=r+1)
		{
			for(int c=0; c < field[r].length; c=c+1)
			{
				if(field[r][c]==MINE)
				{
					drawImage1(r, c, "mine.png");
				}
			}
		}
	}

	//the minesweeper game method
	public void run()
	{
		playMineSweeper();
		//canvas.drawImage(108, 36, "m4.png");
		//canvas.drawImage(144, 36, "m5.png");
	}
}