package server;

import java.awt.Color;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.List;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;

import org.json.JSONArray;
import org.json.JSONObject;

import card.Card;
import card.CardInfo;
import player.BasePlayer;

public class SwingClientGame extends ClientGame {
	//UI STUFF
	JFrame mainFrame;
	JPanel gamePanel;
	JPanel hintPanel;
	JPanel flashPanel;
	JPanel deckPanel;
	JLabel[][] deckUI;
	JLabel[] hintUI;
	JLabel[] flashUI;
	GridBagConstraints layoutConstr;
	// Hints
	JFrame hintFrame;
	JLabel[] hintTypes;

	int clickedPlayer;

	Font font;
	final static Color BACKGROUND = Color.black;

	public static void main(String[] args){
		new SwingClientGame();
	}

	private void createHintUi(){
		hintFrame = new JFrame("Hint UI");
		hintFrame.setSize(450, 150);
		hintFrame.setLayout(new GridLayout(0, 5));
		hintFrame.getContentPane().setBackground(BACKGROUND);
		hintTypes = new JLabel[10];
		hintTypes[0] = new JLabel("1", SwingConstants.CENTER);
		hintTypes[0].setForeground(Color.white);
		hintTypes[0].addMouseListener(new HintMouseListener(true, 0));
		hintTypes[1] = new JLabel("2", SwingConstants.CENTER);
		hintTypes[1].setForeground(Color.white);
		hintTypes[1].addMouseListener(new HintMouseListener(true, 1));
		hintTypes[2] = new JLabel("3", SwingConstants.CENTER);
		hintTypes[2].setForeground(Color.white);
		hintTypes[2].addMouseListener(new HintMouseListener(true, 2));
		hintTypes[3] = new JLabel("4", SwingConstants.CENTER);
		hintTypes[3].setForeground(Color.white);
		hintTypes[3].addMouseListener(new HintMouseListener(true, 3));
		hintTypes[4] = new JLabel("5", SwingConstants.CENTER);
		hintTypes[4].setForeground(Color.white);
		hintTypes[4].addMouseListener(new HintMouseListener(true, 4));
		hintTypes[5] = new JLabel("G", SwingConstants.CENTER);
		hintTypes[5].setForeground(Color.green);
		hintTypes[5].addMouseListener(new HintMouseListener(false, GREEN));
		hintTypes[6] = new JLabel("R", SwingConstants.CENTER);
		hintTypes[6].setForeground(Color.red);
		hintTypes[6].addMouseListener(new HintMouseListener(false, RED));
		hintTypes[7] = new JLabel("Y", SwingConstants.CENTER);
		hintTypes[7].setForeground(Color.yellow);
		hintTypes[7].addMouseListener(new HintMouseListener(false, YELLOW));
		hintTypes[8] = new JLabel("W", SwingConstants.CENTER);
		hintTypes[8].setForeground(Color.white);
		hintTypes[8].addMouseListener(new HintMouseListener(false, WHITE));
		hintTypes[9] = new JLabel("B", SwingConstants.CENTER);
		hintTypes[9].setForeground(Color.blue);
		hintTypes[9].addMouseListener(new HintMouseListener(false, BLUE));
		for(int i=0; i<hintTypes.length; ++i){
			hintTypes[i].setBackground(BACKGROUND);
			hintTypes[i].setFont(font);
			hintFrame.add(hintTypes[i]);
		}
		hintFrame.validate();
		hintFrame.setVisible(false);
	}

	private void toggleHintUi(int x, int y){
		hintFrame.setLocation(x, y);
		hintFrame.setVisible(!hintFrame.isVisible());
	}

	@Override
	protected void createUI() {
		clickedPlayer = 0;
		layoutConstr = new GridBagConstraints();
		mainFrame = new JFrame("Hanabi - Player " + (ownId+1) + " (" + players[ownId].getName() + ")");
		mainFrame.setSize(1000, 650);
		mainFrame.setLocation(0, 0);
		mainFrame.setLayout(new GridBagLayout());
		mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		mainFrame.getContentPane().setBackground(BACKGROUND);
		mainFrame.setVisible(true);
		gamePanel = new JPanel();
		gamePanel.setLayout(new BoxLayout(gamePanel, BoxLayout.Y_AXIS));
		GridLayout deckLayout = new GridLayout(COLORS, 5);

		deckPanel = new JPanel(deckLayout);
		deckPanel.setBackground(BACKGROUND);
		deckUI = new JLabel[COLORS][5];
		for(int i=0; i<COLORS; ++i){
			for(int j=0; j<5; ++j){
				JLabel tmp = new JLabel("X");
				tmp.setBackground(BACKGROUND);
				tmp.setForeground(Color.white);
				tmp.setFont(font);
				tmp.setHorizontalAlignment(JLabel.CENTER);
				deckUI[i][j] = tmp;
				deckPanel.add(deckUI[i][j]);
			}
		}
		hintPanel = new JPanel();
		hintPanel.setBackground(BACKGROUND);
		flashPanel = new JPanel();
		flashPanel.setBackground(BACKGROUND);

		//first empty cell
		layoutConstr.gridx = 0;
		layoutConstr.gridy = 0;
		layoutConstr.weightx = 0.2;
		layoutConstr.weighty = 0.1;
		layoutConstr.gridwidth = 1;
		mainFrame.add(new JPanel(), layoutConstr);

		System.out.println("Number of Players: " + nrOfPlayers);

		layoutConstr.gridx = 1;
		if(nrOfPlayers < 5){
			layoutConstr.weightx = 0.6;
			layoutConstr.gridwidth = 1;
			int index = (nrOfPlayers == 2) ? 1 : 2;
			//mainFrame.add(((SwingPlayer) players[index]).getContainer(), layoutConstr);
			JPanel playerPanel = ((SwingPlayer) players[index]).getPlayerUi();
			mainFrame.add(playerPanel);
			playerPanel.setLayout(new BoxLayout(playerPanel, BoxLayout.X_AXIS));
		} else {
			layoutConstr.weightx = 0.3;
			layoutConstr.gridwidth = 1;
			//mainFrame.add(((SwingPlayer) players[3]).getContainer(), layoutConstr);
			JPanel playerPanel = ((SwingPlayer) players[3]).getPlayerUi();
			mainFrame.add(playerPanel);
			playerPanel.setLayout(new BoxLayout(playerPanel, BoxLayout.X_AXIS));
			layoutConstr.gridx = 2;
			//mainFrame.add(((SwingPlayer) players[2]).getContainer(), layoutConstr);
			playerPanel = ((SwingPlayer) players[2]).getPlayerUi();
			mainFrame.add(playerPanel);
			playerPanel.setLayout(new BoxLayout(playerPanel, BoxLayout.X_AXIS));
		}

		//second empty cell
		layoutConstr.gridx = (nrOfPlayers < 5) ? 2 : 3;
		layoutConstr.weightx = 0.2;
		layoutConstr.gridwidth = 1;
		mainFrame.add(new JPanel(), layoutConstr);

		//4th or 5th player
		layoutConstr.gridx = 0;
		layoutConstr.gridy = 1;
		layoutConstr.weightx = 0.2;
		layoutConstr.weighty = 0.8;
		layoutConstr.gridwidth = 1;
		if(nrOfPlayers == 2 || nrOfPlayers == 3){
			mainFrame.add(new JPanel(), layoutConstr);
		} else {
			int index = (nrOfPlayers == 4) ? 3 : 4;
			//mainFrame.add(((SwingPlayer) players[index]).getContainer(), layoutConstr);
			JPanel playerPanel = ((SwingPlayer) players[index]).getPlayerUi();
			mainFrame.add(playerPanel);
			playerPanel.setLayout(new BoxLayout(playerPanel, BoxLayout.Y_AXIS));
		}

		layoutConstr.gridx = 1;
		layoutConstr.weightx = 0.6;
		layoutConstr.gridwidth = (nrOfPlayers < 5) ? 1 : 2;
		mainFrame.add(gamePanel, layoutConstr);

		//2nd player
		layoutConstr.gridx = (nrOfPlayers < 5) ? 2 : 3;
		layoutConstr.weightx = 0.2;
		layoutConstr.gridwidth = 1;
		if(nrOfPlayers == 2){
			mainFrame.add(new JPanel(), layoutConstr);
		} else {
			//mainFrame.add(((SwingPlayer) players[1]).getContainer(), layoutConstr);
			JPanel playerPanel = ((SwingPlayer) players[1]).getPlayerUi();
			mainFrame.add(playerPanel);
			playerPanel.setLayout(new BoxLayout(playerPanel, BoxLayout.Y_AXIS));
		}

		//third empty cell
		layoutConstr.gridx = 0;
		layoutConstr.gridy = 2;
		layoutConstr.weightx = 0.2;
		layoutConstr.weighty = 0.1;
		layoutConstr.gridwidth = 1;
		mainFrame.add(new JPanel(), layoutConstr);

		layoutConstr.gridx = 1;
		layoutConstr.weightx = 0.8;
		layoutConstr.gridwidth = (nrOfPlayers < 5) ? 1 : 2;
		//mainFrame.add(((SwingPlayer) players[0]).getContainer(), layoutConstr);
		JPanel playerPanel = ((SwingPlayer) players[0]).getPlayerUi();
		mainFrame.add(playerPanel);
		playerPanel.setLayout(new BoxLayout(playerPanel, BoxLayout.X_AXIS));

		//fourth empty cell
		layoutConstr.gridx = (nrOfPlayers < 5) ? 2 : 3;
		layoutConstr.gridy = 2;
		layoutConstr.weightx = 0.2;
		layoutConstr.gridwidth = 1;
		mainFrame.add(new JPanel(), layoutConstr);

		gamePanel.add(hintPanel);
		gamePanel.add(flashPanel);
		gamePanel.add(deckPanel);
		hintUI = new JLabel[MAX_HINTS];
		for(int i=0; i<MAX_HINTS; ++i){
			JLabel tmp = new JLabel();
			tmp.setText("1");
			tmp.setForeground(Color.white);
			tmp.setName("Hint_" + i);
			tmp.setFont(font);
			hintPanel.add(tmp);
			hintUI[i] = tmp;
		}
		flashUI = new JLabel[MAX_FLASHS];
		for(int i=0;i<MAX_FLASHS; ++i){
			JLabel tmp = new JLabel();
			tmp.setText("0");
			tmp.setForeground(Color.white);
			tmp.setName("Flash_" + i);
			tmp.setFont(font);
			flashPanel.add(tmp);
			flashUI[i] = tmp;
		}
		mainFrame.validate();
		createHintUi();
	}

	@Override
	public void loadFont() {
		font = new Font("Shanghai", Font.PLAIN, fontSize);
	}

	@Override
	protected BasePlayer createPlayer(int id, int nrOfCards, String name){
		return new SwingPlayer(id, nrOfCards, name);
	}

	@Override
	protected BasePlayer createPlayer(JSONObject jo){
		return new SwingPlayer(jo);
	}

	@Override
	protected void updateUI() {
		System.out.println("hints: " + hints);
		for(int i=0; i<hints; ++i){
			hintUI[i].setText("1");
		}
		for(int i=hints; i<MAX_HINTS; ++i){
			hintUI[i].setText("0");
		}
		for(int i=0; i<flashs; ++i){
			flashUI[i].setText("1");
		}
		for(int i=flashs; i<MAX_FLASHS; ++i){
			flashUI[i].setText("0");
		}
		for(int i=0; i<deck.length; ++i){
			for(int j=0; j<deck[i].length; ++j){
				String value = String.valueOf(deck[i][j].getValue());
				deckUI[i][j].setText(value + 1);
				deckUI[i][j].setForeground(getColor(deck[i][j].getColorInt()));
			}
		}
	}

	private static Color getColor(int id){
		Color color = null;
		switch(id){
		case 0:
			color = Color.green;
			break;
		case 1:
			color = Color.red;
			break;
		case 2:
			color = Color.yellow;
			break;
		case 3:
			color = Color.white;
			break;
		case 4:
			color = Color.blue;
			break;
		}
		return color;
	}

	private class SwingPlayer extends BasePlayer {
		JPanel playerUi;
		JButton playerName;
		JLabel[] cardUi;

		public SwingPlayer(int id, int nrOfCards, String name){
			super(id, nrOfCards, name);
			playerUi = new JPanel();
			playerUi.setBackground(BACKGROUND);
			playerName = new JButton(name);
			playerName.addMouseListener(new HintListener(id));
			cardUi = new JLabel[nrOfCards];
			playerUi.add(playerName);
			for(int i=0; i<cardUi.length; ++i){
				cardUi[i] = new JLabel();
				cardUi[i].setFont(font);
				cardUi[i].setBackground(BACKGROUND);
				playerUi.add(cardUi[i]);
			}
		}

		public SwingPlayer(JSONObject jo) {
			super(jo);
			playerUi = new JPanel();
			playerUi.setBackground(BACKGROUND);
			playerName = new JButton(name);
			playerName.addMouseListener(new HintListener(id));
			playerUi.add(playerName);
			cardUi = new JLabel[cards.length];
			for(int i=0; i<cardUi.length; ++i){
				JLabel uiCard = new JLabel(String.valueOf(cards[i].getValue() + 1));
				uiCard.setForeground(getColor(cards[i].getColorInt()));
				uiCard.setBackground(BACKGROUND);
				uiCard.setFont(font);
				uiCard.addMouseListener(new PlaceListener(cards[i]));
				cardUi[i] = uiCard;
				playerUi.add(cardUi[i]);
			}
		}

		@Override
		public void setCards(JSONArray ja){
			super.setCards(ja);
			System.out.println("set Swing cards");
			for(int i=0; i<cards.length; ++i){
				if(cardUi[i] == null) cardUi[i] = new JLabel();
				JLabel tmp = cardUi[i];
				tmp.setText(String.valueOf(cards[i].getValue() + 1));
				tmp.setForeground(getColor(cards[i].getColorInt()));
				tmp.addMouseListener(new PlaceListener(cards[i]));
				List<CardInfo> infos = cards[i].getCardInfos();
				String toolTipText = "";
				for(CardInfo info : infos){
					toolTipText += info.isIs() ? "is " : "not ";
					if(info.getType() == HINT_COLOR){
						toolTipText += Card.intColorToText(info.getWhat());
					} else {
						toolTipText += String.valueOf(info.getWhat() + 1);
					}
					toolTipText += " (From Player " + info.getFrom() + ")";
					toolTipText += "\n";
				}
				tmp.setToolTipText(toolTipText);
				cardUi[i] = tmp;
			}
		}

		public JPanel getPlayerUi(){
			return playerUi;
		}
	}

	private class HintMouseListener implements MouseListener {
		private boolean isValue;
		private int value;

		public HintMouseListener(boolean isValue, int value) {
			this.isValue = isValue;
			this.value = value;
		}

		@Override
		public void mouseClicked(MouseEvent e) {
		}
		@Override
		public void mouseEntered(MouseEvent e) {
		}
		@Override
		public void mouseExited(MouseEvent e) {
		}
		@Override
		public void mousePressed(MouseEvent e) {
		}
		@Override
		public void mouseReleased(MouseEvent e) {
			if(SwingUtilities.isLeftMouseButton(e)){
				moveHint(isValue, value, clickedPlayer);
				toggleHintUi(e.getXOnScreen(), e.getYOnScreen());
			}
		}
	}

	private class HintListener implements MouseListener {
		private int playerId;

		public HintListener(int playerId){
			this.playerId = playerId;
		}

		@Override
		public void mouseReleased(MouseEvent e) {
			if(SwingUtilities.isLeftMouseButton(e)){
				System.out.println("Hint!");
				clickedPlayer = playerId;
				toggleHintUi(e.getXOnScreen(), e.getYOnScreen());
			}
		}

		@Override
		public void mousePressed(MouseEvent e) {
		}

		@Override
		public void mouseExited(MouseEvent e) {
		}

		@Override
		public void mouseEntered(MouseEvent e) {
		}

		@Override
		public void mouseClicked(MouseEvent e) {
		}
	}

	private class PlaceListener implements MouseListener {
		private Card c;

		public PlaceListener(Card c){
			this.c = c;
		}

		@Override
		public void mouseReleased(MouseEvent e) {
			if(SwingUtilities.isLeftMouseButton(e)){
				movePlaceCard(c);
			} else if(SwingUtilities.isRightMouseButton(e)){
				moveTrashCard(c);
			}
		}

		@Override
		public void mousePressed(MouseEvent e) {
		}

		@Override
		public void mouseExited(MouseEvent e) {
		}

		@Override
		public void mouseEntered(MouseEvent e) {
		}

		@Override
		public void mouseClicked(MouseEvent e) {
		}
	}
}
