package jrummikub.view.impl;

import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;

import jrummikub.util.Event;
import jrummikub.util.IEvent;
import jrummikub.view.IView.BottomPanelType;

/**
 * A panel that is displayed when a player has won
 */
@SuppressWarnings("serial")
class RoundEndPanel extends JPanel {
	private final static int PANEL_INSET = 15;
	private final static int PANEL_SEPARATOR = 10;
	@SuppressWarnings("unused")
	private final static float PANEL_FIRST_LINE_HEIGHT = 0.375f;
	private final static int PANEL_MAX_WIDTH = 180;
	private final static float MAX_BUTTON_FONT_SIZE = 12;

	private JLabel waitingLabel;
	private JLabel connectionLostLabel;

	private JButton newRoundButton;
	private JButton newGameButton;
	private JButton endProgramButton;

	private Event endProgramEvent = new Event();
	private Event newGameEvent = new Event();
	private Event newRoundEvent = new Event();
	private BottomPanelType type;

	/**
	 * Creates a new WinPanel
	 */
	RoundEndPanel() {
		setLayout(null);
		setBorder(new EmptyBorder(PANEL_INSET, PANEL_INSET, PANEL_INSET,
				PANEL_INSET));

		waitingLabel = new JLabel("Warte auf Host...");
		waitingLabel.setHorizontalAlignment(JLabel.CENTER);
		waitingLabel.setVerticalAlignment(JLabel.CENTER);
		add(waitingLabel);

		connectionLostLabel = new JLabel(
				"Die Verbindung zu einem Spieler ist abgebrochen.");
		connectionLostLabel.setHorizontalAlignment(JLabel.CENTER);
		connectionLostLabel.setVerticalAlignment(JLabel.CENTER);
		add(connectionLostLabel);

		createButtons();
	}

	private void createButtons() {
		newRoundButton = new JButton("Neue Runde");
		newRoundButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				newRoundEvent.emit();
			}
		});
		add(newRoundButton);

		newGameButton = new JButton("Neues Spiel");
		newGameButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				newGameEvent.emit();
			}
		});
		add(newGameButton);

		endProgramButton = new JButton("Programm verlassen");
		endProgramButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				endProgramEvent.emit();
			}
		});
		add(endProgramButton);

		addComponentListener(new ComponentAdapter() {
			@Override
			public void componentResized(ComponentEvent e) {
				rescale();
			}
		});
	}

	/**
	 * The new round event is emitted when the player wants to start a new round
	 * 
	 * @return the event
	 */
	IEvent getNewRoundEvent() {
		return newRoundEvent;
	}

	IEvent getNewGameEvent() {
		return newGameEvent;
	}

	/**
	 * The end program is emitted when the player wants to quit the program
	 * 
	 * @return the event
	 */
	IEvent getEndProgramEvent() {
		return endProgramEvent;
	}

	private void rescale() {
		Insets insets = getInsets();
		int x = insets.left, y = insets.top, width = getWidth() - insets.left
				- insets.right, height = getHeight() - insets.top - insets.bottom;

		if (width > PANEL_MAX_WIDTH) {
			x += (width - PANEL_MAX_WIDTH) / 4;
			width = width / 2 + PANEL_MAX_WIDTH / 2;
		}

		if (type == BottomPanelType.WIN_PANEL) {
			rescaleWinPanel(x, y, width, height);
		} else if (type == BottomPanelType.NETWORK_WIN_PANEL) {
			rescaleNetworkWinPanel(x, y, width, height);
		} else if (type == BottomPanelType.NETWORK_CONNECTION_LOST_PANEL) {
			rescaleNetworkConnectionLostPanel(x, y, width, height);
		}
	}

	private void rescaleWinPanel(int x, int y, int width, int height) {
		int buttonWidth = (width - 2 * PANEL_SEPARATOR) / 3;
		int buttonHeight = height;
		int buttonY = y;

		float fontSize = (float) Math.sqrt(buttonWidth * buttonHeight) / 5;
		if (fontSize > MAX_BUTTON_FONT_SIZE)
			fontSize = MAX_BUTTON_FONT_SIZE;

		waitingLabel.setVisible(false);
		connectionLostLabel.setVisible(false);
		newRoundButton.setBounds(x, buttonY, buttonWidth, buttonHeight);
		newRoundButton.setFont(newRoundButton.getFont().deriveFont(fontSize));
		newRoundButton.setVisible(true);

		newGameButton.setBounds(x + buttonWidth + PANEL_SEPARATOR, buttonY,
				buttonWidth, buttonHeight);
		newGameButton.setFont(newGameButton.getFont().deriveFont(fontSize));

		endProgramButton.setBounds(x + 2 * (buttonWidth + PANEL_SEPARATOR),
				buttonY, buttonWidth, buttonHeight);
		endProgramButton.setFont(endProgramButton.getFont().deriveFont(fontSize));
	}

	private void rescaleNetworkWinPanel(int x, int y, int width, int height) {
		int buttonWidth = (width - PANEL_SEPARATOR) / 2;
		int buttonHeight = height * 2 / 3 - PANEL_SEPARATOR;
		int buttonY = y + height - buttonHeight;
		int labelHeight = height - buttonHeight - PANEL_SEPARATOR;

		float fontSize = (float) Math.sqrt(buttonWidth * buttonHeight) / 5;
		if (fontSize > MAX_BUTTON_FONT_SIZE)
			fontSize = MAX_BUTTON_FONT_SIZE;

		waitingLabel.setBounds(x, y, width, labelHeight);
		waitingLabel.setVisible(true);
		connectionLostLabel.setVisible(false);

		newRoundButton.setVisible(false);

		newGameButton.setBounds(x, buttonY, buttonWidth, buttonHeight);
		newGameButton.setFont(newGameButton.getFont().deriveFont(fontSize));

		endProgramButton.setBounds(x + buttonWidth + PANEL_SEPARATOR, buttonY,
				buttonWidth, buttonHeight);
		endProgramButton.setFont(endProgramButton.getFont().deriveFont(fontSize));
	}

	private void rescaleNetworkConnectionLostPanel(int x, int y, int width,
			int height) {
		int buttonWidth = (width - PANEL_SEPARATOR) / 2;
		int buttonHeight = height * 2 / 3 - PANEL_SEPARATOR;
		int buttonY = y + height - buttonHeight;
		int labelHeight = height - buttonHeight - PANEL_SEPARATOR;

		float fontSize = (float) Math.sqrt(buttonWidth * buttonHeight) / 5;
		if (fontSize > MAX_BUTTON_FONT_SIZE)
			fontSize = MAX_BUTTON_FONT_SIZE;

		waitingLabel.setVisible(false);
		connectionLostLabel.setBounds(x, y, width, labelHeight);
		connectionLostLabel.setVisible(true);

		newRoundButton.setVisible(false);

		newGameButton.setBounds(x, buttonY, buttonWidth, buttonHeight);
		newGameButton.setFont(newGameButton.getFont().deriveFont(fontSize));

		endProgramButton.setBounds(x + buttonWidth + PANEL_SEPARATOR, buttonY,
				buttonWidth, buttonHeight);
		endProgramButton.setFont(endProgramButton.getFont().deriveFont(fontSize));
	}

	void setType(BottomPanelType type) {
		this.type = type;
		rescale();
	}
}
