package jrummikub.view.impl;

import java.awt.Color;
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 java.awt.event.ComponentListener;
import java.text.DecimalFormat;

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

import jrummikub.util.Event;
import jrummikub.util.IEvent;
import jrummikub.view.IPlayerPanel;

/**
 * Implementation of the player panel
 */
@SuppressWarnings("serial")
class PlayerPanel extends JPanel implements IPlayerPanel {
	private final static int SIDE_PANEL_INSET = 15;
	private final static int SIDE_PANEL_SEPARATOR = 10;
	private final static float SIDE_PANEL_FIRST_LINE_HEIGHT = 0.375f;
	private final static int SIDE_PANEL_MAX_WIDTH = 180;
	private final static float MAX_BUTTON_FONT_SIZE = 12;

	private final static DecimalFormat secondFormat = new DecimalFormat("00");

	private HandPanel hand;

	private JPanel leftPanel, rightPanel;

	private JLabel currentPlayerNameLabel;
	private JButton sortByGroupsButton;
	private JButton sortByRunsButton;
	private JProgressBar timeBar;
	private JButton endTurnButton;

	private Event sortByGroupsEvent = new Event();
	private Event sortByRunsEvent = new Event();
	private Event endTurnEvent = new Event();

	@Override
	public HandPanel getHandPanel() {
		return hand;
	}

	/**
	 * Sets the current player name
	 * 
	 * @param playerName
	 *          the player name
	 */
	void setCurrentPlayerName(String playerName) {
		currentPlayerNameLabel.setText(playerName);
	}

	@Override
	public void setTimeLeft(int time) {
		timeBar.setValue(time);
		timeBar.setString(Integer.toString(time / 60) + ":"
				+ secondFormat.format(time % 60));

		if (time <= 10)
			timeBar.setForeground(Color.RED);
		else
			timeBar.setForeground(Color.BLACK);
	}

	@Override
	public IEvent getSortByGroupsEvent() {
		return sortByGroupsEvent;
	}

	@Override
	public IEvent getSortByRunsEvent() {
		return sortByRunsEvent;
	}

	@Override
	public IEvent getEndTurnEvent() {
		return endTurnEvent;
	}

	private void createLeftPanel() {
		leftPanel = new JPanel();
		leftPanel.setLayout(null);
		leftPanel.setBorder(new EmptyBorder(SIDE_PANEL_INSET, SIDE_PANEL_INSET,
				SIDE_PANEL_INSET, SIDE_PANEL_INSET));

		currentPlayerNameLabel = new JLabel();
		currentPlayerNameLabel.setHorizontalAlignment(JLabel.CENTER);
		currentPlayerNameLabel.setHorizontalTextPosition(JLabel.CENTER);
		currentPlayerNameLabel.setVerticalAlignment(JLabel.CENTER);
		currentPlayerNameLabel.setVerticalTextPosition(JLabel.CENTER);
		leftPanel.add(currentPlayerNameLabel);

		sortByGroupsButton = new JButton("<html><center>Nach Sammlungen sortieren");
		sortByGroupsButton.setFont(sortByGroupsButton.getFont().deriveFont(0));
		sortByGroupsButton.setMargin(new Insets(0, 0, 0, 0));
		sortByGroupsButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				sortByGroupsEvent.emit();
			}
		});
		leftPanel.add(sortByGroupsButton);

		sortByRunsButton = new JButton("<html><center>Nach Reihen sortieren");
		sortByRunsButton.setFont(sortByRunsButton.getFont().deriveFont(0));
		sortByRunsButton.setMargin(new Insets(0, 0, 0, 0));
		sortByRunsButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				sortByRunsEvent.emit();
			}
		});
		leftPanel.add(sortByRunsButton);

		leftPanel.addComponentListener(new LeftPanelResizeListener());
	}

	private void createRightPanel() {
		rightPanel = new JPanel();
		rightPanel.setLayout(null);
		rightPanel.setBorder(new EmptyBorder(SIDE_PANEL_INSET, SIDE_PANEL_INSET,
				SIDE_PANEL_INSET, SIDE_PANEL_INSET));

		timeBar = new JProgressBar(0, 60);
		timeBar.setStringPainted(true);
		rightPanel.add(timeBar);

		endTurnButton = new JButton("Zug beenden");
		endTurnButton.setFont(endTurnButton.getFont().deriveFont(0));
		endTurnButton.setMargin(new Insets(0, 0, 0, 0));
		endTurnButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				endTurnEvent.emit();
			}
		});

		rightPanel.add(endTurnButton);

		rightPanel.addComponentListener(new RightPanelResizeListener());
	}

	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;
		int boardWidth = hand.getWidth();
		int panelWidth = (width - boardWidth) / 2;

		leftPanel.setBounds(x, y, panelWidth, height);
		hand.setBounds(x + panelWidth, y, boardWidth, height);
		rightPanel.setBounds(x + panelWidth + boardWidth, y, panelWidth, height);

		leftPanel.validate();
		rightPanel.validate();
	}

	/**
	 * Creates a new PlayerPanel instance
	 */
	PlayerPanel() {
		setLayout(null);

		createLeftPanel();
		add(leftPanel);

		hand = new HandPanel();
		add(hand);

		createRightPanel();
		add(rightPanel);

		ComponentListener rescaleListener = new ComponentAdapter() {
			@Override
			public void componentResized(ComponentEvent e) {
				rescale();
			}
		};

		addComponentListener(rescaleListener);
		hand.addComponentListener(rescaleListener);
	}

	private class LeftPanelResizeListener extends ComponentAdapter {
		@Override
		public void componentResized(ComponentEvent e) {
			Insets insets = leftPanel.getInsets();
			int x = insets.left, y = insets.top, width = leftPanel.getWidth()
					- insets.left - insets.right, height = leftPanel.getHeight()
					- insets.top - insets.bottom;

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

			int firstLineHeight = (int) ((height - SIDE_PANEL_SEPARATOR) * SIDE_PANEL_FIRST_LINE_HEIGHT);
			int buttonWidth = (width - SIDE_PANEL_SEPARATOR) / 2;
			int buttonHeight = height - SIDE_PANEL_SEPARATOR - firstLineHeight;
			float fontSize = (float) Math.sqrt(buttonWidth * buttonHeight) / 6;
			if (fontSize > MAX_BUTTON_FONT_SIZE)
				fontSize = MAX_BUTTON_FONT_SIZE;

			currentPlayerNameLabel.setBounds(x, y, width, firstLineHeight);
			sortByGroupsButton.setBounds(x, y + firstLineHeight
					+ SIDE_PANEL_SEPARATOR, buttonWidth, buttonHeight);
			sortByRunsButton.setBounds(x + buttonWidth + SIDE_PANEL_SEPARATOR, y
					+ firstLineHeight + SIDE_PANEL_SEPARATOR, buttonWidth, buttonHeight);

			sortByGroupsButton.setFont(sortByGroupsButton.getFont().deriveFont(
					fontSize));
			sortByRunsButton.setFont(sortByRunsButton.getFont().deriveFont(fontSize));
		}
	}

	private class RightPanelResizeListener extends ComponentAdapter {
		@Override
		public void componentResized(ComponentEvent e) {
			Insets insets = rightPanel.getInsets();
			int x = insets.left, y = insets.top, width = rightPanel.getWidth()
					- insets.left - insets.right, height = rightPanel.getHeight()
					- insets.top - insets.bottom;

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

			int firstLineHeight = (int) ((height - SIDE_PANEL_SEPARATOR) * SIDE_PANEL_FIRST_LINE_HEIGHT);
			int buttonWidth = width;
			int buttonHeight = height - SIDE_PANEL_SEPARATOR - firstLineHeight;
			float fontSize = (float) Math.sqrt(buttonWidth * buttonHeight) / 5;
			if (fontSize > MAX_BUTTON_FONT_SIZE)
				fontSize = MAX_BUTTON_FONT_SIZE;

			timeBar.setBounds(x, y, width, firstLineHeight);
			endTurnButton.setBounds(x, y + firstLineHeight + SIDE_PANEL_SEPARATOR,
					buttonWidth, buttonHeight);
			endTurnButton.setFont(endTurnButton.getFont().deriveFont(fontSize));
		}
	}
}
