package player.gamer.statemachine.sadna;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.List;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class GUIFourInARow implements FourInARow {

	enum States{MY_MOVE, OPPONENT_MOVE, NO_GAME};
	States state = States.NO_GAME;
	
	private MainPane fr;
	private JLabel status;
	private ImageIcon myIcon;
	private ImageIcon opponentIcon;
	
	private int move;
	private int[] heightCoins;
	private boolean clicked = false;
	private JLabel[][] blocks;
	
	Object syncObj = new Object();
	
	/*--- Interface ---*/
	
	@Override
	public void fourStart(String role) {
		ImageIcon redCoin = new ImageIcon(getClass().getClassLoader().getResource("resource/red.png"));
		ImageIcon blackCoin = new ImageIcon(getClass().getClassLoader().getResource("resource/black.png"));
		
		// init parameters
		blocks = new JLabel[6][8];
		heightCoins = new int[8];
		
		// create main pane
		fr = new MainPane();
		fr.setTitle("Four In A Row: " + role);
		
		// set Role
		if (role.equals("red")) {
			status = new JLabel(" Your Turn");
			state = States.MY_MOVE;
			myIcon = redCoin;
			opponentIcon = blackCoin;
		} else {
			status = new JLabel(" Opponent Turn");
			state = States.OPPONENT_MOVE;
			myIcon = blackCoin;
			opponentIcon = redCoin;
		}
		fr.getContentPane().add(status, BorderLayout.SOUTH);
		
		// set frame parameters
		fr.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		fr.setResizable(false);
		fr.pack();
		Dimension parentSize = Toolkit.getDefaultToolkit().getScreenSize();
		fr.setLocation(parentSize.width / 2 - fr.getWidth() / 2, parentSize.height / 2 - fr.getHeight() / 2);
		fr.setVisible(true);
		fr.toFront();
	}

	@Override
	public int fourMove(List<Integer> moved, List<Integer> options,	long timelimit) {
		
		// paint opponent move
		if (!moved.isEmpty()) {
			int opponentMove = moved.get(0)-1;
			blocks[heightCoins[opponentMove]][opponentMove].setIcon(opponentIcon);
			heightCoins[opponentMove]++;
		}
		
		state = States.MY_MOVE;
		status.setText(" Your Turn");
		
		// wait for user to make a move (click on a column)
		synchronized (syncObj) {
			clicked = false;
			while (!clicked) {
				try {
					syncObj.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
		
		state = States.OPPONENT_MOVE;
		status.setText(" Opponent Turn");
		
		return options.indexOf(move+1);
	}

	@Override
	public void fourEnd(int score) {
		state = States.NO_GAME;
		status.setText(" Game Ended");

		// Alert user on score
		if (score == 0) {
			new AlertDialog("You Lost :(");
		} else if (score == 100) {
			new AlertDialog("You Won :)");
		} else {
			new AlertDialog("It's a Tie :|");
		}
	
		// close window
		fr.dispose();
	}

	@Override
	public String getName() {
		return "RealGamer";
	}
	
	/*--- Inner Classes ---*/

	public class AlertDialog extends JDialog implements ActionListener {
		public AlertDialog(String message) {
			super(fr, "Alert", true);
			
			// create alert window
			JPanel messagePane = new JPanel();
			messagePane.add(new JLabel(message));
			getContentPane().add(messagePane);
			JPanel buttonPane = new JPanel();
			JButton button = new JButton("OK");
			buttonPane.add(button);
			button.addActionListener(this);
			getContentPane().add(buttonPane, BorderLayout.SOUTH);
			setDefaultCloseOperation(DISPOSE_ON_CLOSE);
			pack();
			
			// set window location
			Dimension parentSize = fr.getSize();
			Point p = fr.getLocation();
			setLocation(p.x + parentSize.width / 2 - getWidth() / 2, p.y + parentSize.height / 2 - getHeight() / 2);
			
			setVisible(true);
		}

		public void actionPerformed(ActionEvent e) {
			// close alert
			setVisible(false);
			dispose();
		}
	}

	class MainPane extends JFrame {
		public MainPane() {
			// create background board
			JPanel board = new JPanel();
			board.setLayout(new GridLayout(6, 8, -1, -1));
			
			ImageIcon backBlock = new ImageIcon(getClass().getClassLoader().getResource("resource/white.png"));
			
			for (int i = 5; i >= 0; i--) {
				for (int j = 0; j < 8; j++) {
					blocks[i][j] = new JLabel(backBlock);
					board.add(blocks[i][j]);
				}
			}
			
			board.addMouseListener(new ClickEventHandler());
			
			getContentPane().setLayout(new BorderLayout());
			getContentPane().add(board, BorderLayout.CENTER);
		}
	}

	public class ClickEventHandler extends MouseAdapter {
		@Override
		public void mouseClicked(MouseEvent event) {
			
			// only work on user move
			if (state != States.MY_MOVE) {
				return;
			}
			
			// calculate user move (the column the user clicked on)
			int x = event.getX();
			move = x / 80;
	
			// validate the move is legal
			if (heightCoins[move] == 6) {
				new AlertDialog("Illegal move - column is already full");
				return;
			}
			
			// paint user's coin
			blocks[heightCoins[move]][move].setIcon(myIcon);
			heightCoins[move]++;
			
			// notify user move done
			synchronized (syncObj) {
				clicked = true;
				syncObj.notify();	
			}
		}
	}
}
