package jrummikub.view;

import java.awt.Color;
import java.util.List;
import java.util.Set;

import jrummikub.model.GameSettings;
import jrummikub.model.PlayerSettings.Type;
import jrummikub.model.StoneColor;
import jrummikub.util.IEvent;
import jrummikub.util.IEvent1;
import jrummikub.util.IEvent2;

/**
 * The panel for the game setup
 */
public interface ISettingsPanel {
	/**
	 * The list of player colors
	 */
	public final static Color[] PLAYER_COLORS = { new Color(1.0f, 0, 0), // red
			new Color(0, 1.0f, 0), // lime
			new Color(1.0f, 1.0f, 0), // yellow
			new Color(0, 0, 1.0f), // blue
			new Color(1.0f, 0, 1.0f), // fuchsia
			new Color(0, 1.0f, 1.0f), // aqua
			new Color(0.5f, 0, 0), // maroon
			new Color(0, 0.5f, 0), // green
			new Color(0.5f, 0.5f, 0), // olive
			new Color(0, 0, 0.5f), // navy
			new Color(0.5f, 0, 0.5f), // purple
			new Color(0, 0.5f, 0.5f), // teal
			new Color(0, 0, 0), // black
			new Color(0.5f, 0.5f, 0.5f), // gray
			new Color(0.75f, 0.75f, 0.75f), // silver
			new Color(1.0f, 1.0f, 1.0f), // white
	};

	/**
	 * Sets the settings mode according to the point of the game
	 * 
	 * @param mode
	 *            settings mode to be set (join, offer, network, default)
	 */
	public void setSettingsMode(SettingsMode mode);

	/**
	 * The add player event is emitted when the user wants to add a player to
	 * the player list
	 * 
	 * @return the event
	 */
	public IEvent getAddPlayerEvent();

	/**
	 * The remove player event is emitted when the user wants to remove a player
	 * remove the player list
	 * 
	 * @return the event
	 */
	public IEvent1<Integer> getRemovePlayerEvent();

	/**
	 * The change player color event is emitted when the user wants change a
	 * player's color
	 * 
	 * @return the event
	 */
	public IEvent2<Integer, Color> getChangePlayerColorEvent();

	/**
	 * The change player color event is emitted when the user wants change a
	 * player's name
	 * 
	 * @return the event
	 */
	public IEvent2<Integer, String> getChangePlayerNameEvent();

	/**
	 * The change player color event is emitted when the user wants change a
	 * player's type
	 * 
	 * @return the event
	 */
	public IEvent2<Integer, Type> getChangePlayerTypeEvent();

	/**
	 * The change initial meld threshold event is emitted when the user wants
	 * change the initial meld threshold
	 * 
	 * @return the event
	 */
	public IEvent1<Integer> getChangeInitialMeldThresholdEvent();

	/**
	 * The change StoneSet number event is emitted when the user wants to use
	 * more or less than 2 StoneSets per color
	 * 
	 * @return number of SoneSets
	 */
	public IEvent1<Integer> getChangeStoneSetNumberEvent();

	/**
	 * The change number of Stones dealt event is emitted when the user wants to
	 * be dealt more or less than 14 Stones at the game start
	 * 
	 * @return number of Stones dealt
	 */
	public IEvent1<Integer> getChangeNumberOfStonesDealtEvent();

	/**
	 * The change highest value event is emitted when the user wants to set the
	 * highest Stone value
	 * 
	 * @return highest Stone value
	 */
	public IEvent1<Integer> getChangeHighestValueEvent();

	/**
	 * The change Stone colors event is emitted when the user chooses the stone
	 * colors to play with. Minimum 3, maximum 8
	 * 
	 * @return set of used StoneColors
	 */
	public IEvent1<Set<StoneColor>> getChangeStoneColorsEvent();

	/**
	 * the start game event is emitted when the user wants to start the game
	 * 
	 * @return the event
	 */
	public IEvent getStartGameEvent();

	/**
	 * Sets an error to display
	 * 
	 * @param error
	 *            the kind of error
	 */
	public void setError(SettingsError error);

	/**
	 * Enables or disables the start game button
	 * 
	 * @param enable
	 *            specifies if the button is to be enabled or disabled
	 */
	public void enableStartGameButton(boolean enable);

	/**
	 * Enables or disables the add player button
	 * 
	 * @param enable
	 *            specifies if the button is to be enabled or disabled
	 */
	public void enableAddPlayerButton(boolean enable);

	/**
	 * Enables or disables the remove player buttons
	 * 
	 * @param enable
	 *            specifies if the buttons are to be enabled or disabled
	 */

	public void enableRemovePlayerButtons(List<Boolean> enable);

	/**
	 * Sets the game settings to display
	 * 
	 * @param gameSettings
	 *            the settings
	 */
	public void setGameSettings(GameSettings gameSettings);

	/**
	 * Emitted when the joker number is changed
	 * 
	 * @return the event
	 */
	public IEvent1<Integer> getChangeJokerNumberEvent();

	/**
	 * Emitted when totalTime for a turn is changed
	 * 
	 * @return the event
	 */
	public IEvent1<Integer> getChangeTimeEvent();

	/**
	 * Emitted when no limits is chosen
	 * 
	 * @return the event
	 */
	public IEvent1<Boolean> getChangeNoLimitsEvent();

	/**
	 * Emitted when the variables are reset to the default values
	 * 
	 * @return the event
	 */
	public IEvent getSetVariantDefaultEvent();

	/**
	 * Emitted when the children variant is chosen
	 * 
	 * @return the event
	 */
	public IEvent getSetVariantChildrenEvent();

	/**
	 * Emitted when the user wants to go back to the panel before
	 * 
	 * @return the event
	 */
	public IEvent getBackEvent();

	/**
	 * Sets the types of players allowed at the given point in game
	 * 
	 * @param choices
	 *            list of types for each player
	 */
	public void setPlayerTypeChoices(List<List<Type>> choices);

	/**
	 * Sets the names of players editable if allowed at the given point in game
	 * 
	 * @param editable
	 *            states if the players name is editable for each player
	 */
	public void setPlayerNamesEditable(List<Boolean> editable);

	/**
	 * Emitted when a new game is started and looking for players
	 * 
	 * @return the event
	 */
	public IEvent getOfferGameEvent();

	/**
	 * Sets the player colors which can be chosen
	 * 
	 * @param colors
	 *            a Set of colors which are not taken yet
	 */
	public void setPlayerColors(Set<Color> colors);

	/**
	 * Specifies the different kinds of settings errors that can be displayed
	 */
	public enum SettingsError {
		/** Everything is ok */
		NO_ERROR,
		/** A player name is used twice */
		DUPLICATE_PLAYER_NAME_ERROR,
		/** A player has an empty name */
		NO_PLAYER_NAME_ERROR,
		/** More Stones than present would be dealed */
		NOT_ENOUGH_STONES_ERROR,
		/** Less than 3 colors are selected */
		NOT_ENOUGH_COLORS_ERROR,

		// warnings
		/** threshold higher 100 */
		TOO_HIGH_THRESHOLD_WARNING,
		/** Only computer players added */
		COMPUTER_PLAYERS_ONLY_WARNING
	}

	/**
	 * SettingsPanel can be used with different functions in different
	 * situations
	 */
	public enum SettingsMode {
		/** Local game settings */
		DEFAULT,
		/** */
		NETWORK_SETUP,
		/** */
		NETWORK_OFFER,
		/** */
		NETWORK_JOIN
	}
}