import java.awt.Component;
import java.awt.GridLayout;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JSeparator;

public class SwingGomoku extends JFrame implements ActionListener {
	private final int FILE_NEW = 10001;
	private final int FILE_EXIT = 19999;
	private final int BOARD_SIZE = 10101;
	private final int CONN_SIZE = 10102;

	private ImageIcon icons[] = { new ImageIcon("not.gif"),
			new ImageIcon("cross.gif") };

	private int mRow = 6;
	private int mCol = 4;
	private int mConn = 4;

	private int[][] mBoard;
	private int mPlayer = 0;
	private int mCount = 0;
	private boolean mContGame = false;

	public SwingGomoku() throws HeadlessException {
		this(3, 3, 3);
	}

	public SwingGomoku(int mRow, int mCol, int mConn) throws HeadlessException {
		super();
		this.mRow = mRow;
		this.mCol = mCol;
		this.mConn = mConn;
	}

	public void newGame() {
		String s = String.format("%d x %d 棋盤  %d 個連線遊戲  by 東吳 林旭陽", mRow, mCol,
				mConn);
		setTitle(s);

		int w = mCol * 55;
		int h = mRow * 55;

		setSize(w, h);

		newBoard();
		setVisible(true);

		mPlayer = 0;
		mCount = 0;
		mPlayer = 0;
		mCount = 0;

	}

	private void newBoard() {
		mBoard = new int[mRow][mCol];
		for (int r = 0; r < mRow; r++) {
			for (int c = 0; c < mCol; c++) {
				mBoard[r][c] = -1; // not fill yet
			}
		}

		if (mContGame) {
			Component[] components = getComponents();
			for (Component component : getComponents()) {
				remove(component);
			}
			mContGame = true;
		}
		setLayout(new GridLayout(mRow, mCol, 1, 1));

		for (int k = 0; k < mRow * mCol; k++) {
			JButton btn = new JButton();
			btn.setActionCommand(String.valueOf(k));
			btn.addActionListener(this);
			add(btn);
		}
	}

	private void gameLayout() {
		String title = String
				.format("%dx%d-%d連線遊戲  by 東吳資管", mRow, mCol, mConn);
		setTitle(title);
		int w = mCol * 88;
		int h = mRow * 88;
		setSize(w, h);
	}

	public JMenuBar createMenuBar() {
		JMenuBar menubar = new JMenuBar();
		JMenu filemenu = new JMenu("檔案");
		filemenu.add(new JSeparator());
		JMenu gamemenu = new JMenu("遊戲");

		JMenuItem fileNew = new JMenuItem("新遊戲");
		fileNew.setActionCommand(String.valueOf(FILE_NEW));
		fileNew.addActionListener(this);

		JMenuItem fileExit = new JMenuItem("結束");
		fileExit.setActionCommand(String.valueOf(FILE_EXIT));
		fileExit.addActionListener(this);

		JMenuItem boardSize = new JMenuItem("遊戲版大小");
		boardSize.setActionCommand(String.valueOf(BOARD_SIZE));
		boardSize.addActionListener(this);
		JMenuItem connSize = new JMenuItem("連線數目");
		connSize.setActionCommand(String.valueOf(CONN_SIZE));
		connSize.addActionListener(this);

		filemenu.add(fileNew);
		filemenu.addSeparator();
		filemenu.add(fileExit);

		gamemenu.add(boardSize);
		gamemenu.add(connSize);

		menubar.add(filemenu);
		menubar.add(gamemenu);

		return menubar;
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		String cmd = e.getActionCommand();
		int loc = Integer.parseInt(cmd);
		if (loc >= 10000) { // menu item
			switch (loc) {
			case FILE_NEW:
				newGame();
				break;

			case FILE_EXIT:
				System.exit(0);
				break;
			case BOARD_SIZE:
				try {
					String s = JOptionPane.showInputDialog("請輸入棋盤列數：");
					int tmp = Integer.parseInt(s);
					if (tmp <= 30 && tmp > 0) {
						mRow = tmp;
					}
					s = JOptionPane.showInputDialog("請輸入棋盤行數：");
					tmp = Integer.parseInt(s);
					if (tmp <= 30 && tmp > 0) {
						mCol = tmp;
					}
				} catch (Exception e1) {
					// TODO: handle exception
				}
				break;
			case CONN_SIZE:
				try {
					String s = JOptionPane.showInputDialog("請輸入連線數目：");
					int tmp = Integer.parseInt(s);
					if (tmp <= 30 && tmp > 0) {
						mConn = tmp;
					}
				} catch (Exception e1) {
					// TODO: handle exception
				}
				break;
			default:
				break;
			}
			return;
		}

		int row = loc / mCol;
		int col = loc % mCol;
		if (mBoard[row][col] != -1)
			return; // already clicked

		mBoard[row][col] = mPlayer;

		JButton btn = (JButton) e.getSource();
		btn.setIcon(icons[mPlayer]);
		int win = checkBoard(row, col, mPlayer, mConn);
		mPlayer = 1 - mPlayer;
		mCount++;
		String title = String.format("%dx%d-%d連線遊戲 ：按 %d 次", mRow, mCol, mConn,
				mCount);
		setTitle(title);

		if (win != -1) {
			JOptionPane.showMessageDialog(null, "玩家 " + (2 - mPlayer) + " 贏了！",
					"遊戲結束", JOptionPane.INFORMATION_MESSAGE);
			// System.exit(0);
			// newGame();
			askUserCont();
		} else {
			if (mCount == mRow * mCol) {
				JOptionPane.showMessageDialog(null, "平手！", "遊戲結束",
						JOptionPane.INFORMATION_MESSAGE);
				// System.exit(0);
				// newGame();
				askUserCont();
			}
		}
	}

	public void askUserCont() {
		JDialog.setDefaultLookAndFeelDecorated(true);
		int response = JOptionPane.showConfirmDialog(null, "繼續完遊戲?", "遊戲確認",
				JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
		if (response == JOptionPane.NO_OPTION) {
			System.exit(0);
		} else if (response == JOptionPane.YES_OPTION) {
			newGame();
		} else if (response == JOptionPane.CLOSED_OPTION) {
			System.exit(0);
		}

	}

	// check 連線個數
	private int checkBoard(int row, int col, int player, int conn_count) {
		int no_one_win = -1;
		int r, c;

		// -- check row
		int same_count = 1; // self location is 1
		// left
		r = row - 1;
		while (r >= 0) {
			if (mBoard[r][col] == player)
				same_count++;
			else
				break;
			r--;
		}
		// right
		r = row + 1;
		while (r < mCol) {
			if (mBoard[r][col] == player)
				same_count++;
			else
				break;
			r++;
		}
		// check row done ?
		if (same_count >= conn_count) {
			return player;
		}

		// -- check column
		same_count = 1;
		// up
		c = col - 1;
		while (c >= 0) {
			if (mBoard[row][c] == player)
				same_count++;
			else
				break;
			c--;
		}
		// down
		c = col + 1;
		while (c < mCol) {
			if (mBoard[row][c] == player)
				same_count++;
			else
				break;
			c++;
		}
		// check column done ?
		if (same_count >= conn_count) {
			return player;
		}

		// -- check diagonal
		same_count = 1;
		// up, left
		r = row - 1;
		c = col - 1;
		while (r >= 0 && c >= 0) {
			if (mBoard[r][c] == player)
				same_count++;
			else
				break;
			r--;
			c--;
		}
		// down, right
		r = row + 1;
		c = col + 1;
		while (r < mRow && c < mCol) {
			if (mBoard[r][c] == player)
				same_count++;
			else
				break;
			r++;
			c++;
		}
		// check diagonal done ?
		if (same_count >= conn_count) {
			return player;
		}

		// -- check reverse diagonal
		same_count = 1;
		// up, right
		r = row - 1;
		c = col + 1;
		while (r >= 0 && c < mCol) {
			if (mBoard[r][c] == player)
				same_count++;
			else
				break;
			r--;
			c++;
		}
		// down, left
		r = row + 1;
		c = col - 1;
		while (r < mRow && c >= 0) {
			if (mBoard[r][c] == player)
				same_count++;
			else
				break;
			r++;
			c--;
		}
		// check reverse diagonal done ?
		if (same_count >= conn_count) {
			return player;
		}

		return no_one_win;
	}

	public static void main(String[] args) {
		SwingGomoku game = new SwingGomoku();
		game.gameLayout();

		game.setJMenuBar(game.createMenuBar());
		game.newGame();

	}

}
