package client.control.menu;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.SwingUtilities;
import javax.swing.UIManager;

/*import net.infonode.gui.laf.InfoNodeLookAndFeel;
import net.sourceforge.napkinlaf.NapkinLookAndFeel;

import org.pushingpixels.substance.api.skin.SubstanceBusinessBlackSteelLookAndFeel;
import org.pushingpixels.substance.api.skin.SubstanceChallengerDeepLookAndFeel;
import org.pushingpixels.substance.api.skin.SubstanceCremeCoffeeLookAndFeel;
import org.pushingpixels.substance.api.skin.SubstanceOfficeBlue2007LookAndFeel;

import ch.randelshofer.quaqua.leopard.Quaqua15LeopardCrossPlatformLookAndFeel;*/
import client.Application;
import client.ApplicationProperties;
/*
import com.seaglasslookandfeel.SeaGlassLookAndFeel;

import de.centigrade.laf.textile.TextileLookAndFeel;
import de.javasoft.plaf.synthetica.SyntheticaBlackEyeLookAndFeel;
*/
/**
 * This class handle the theme's switching feature
 *
 * @author Dream Team - ING2
 *
 */
public class ThemeManager implements ActionListener {

	/** Default theme chosen at application's launch */
	public static final String DEFAULT_THEME = "Default";
	/**
	 * Theme developed by <a href="http://www.javasoft.de/synthetica/">Jyloo
	 * software</a>
	 */
	public static final String SYNTHETICA_BLACK_EYE = "Synthetica Black Eye";
	/**
	 * Theme developed by <a href="https://substance.dev.java.net/">developpers'
	 * community</a>
	 */
	public static final String SUBSTANCE_BUSINESS_BLACK_STEEL = "Substance Business Black Steel";
	/**
	 * Theme developed by <a href="https://substance.dev.java.net/">developpers'
	 * community</a>
	 */
	public static final String SUBSTANCE_CREME_COFFEE = "Substance Creme Coffee";
	/**
	 * Theme developed by <a href="https://substance.dev.java.net/">developpers'
	 * community</a>
	 */
	public static final String SUBSTANCE_OFFICE_BLUE_2007 = "Substance Office Blue 2007";
	/**
	 * Theme developed by <a href="https://substance.dev.java.net/">developpers'
	 * community</a>
	 */
	public static final String SUBSTANCE_CHALLENGER_DEEP = "Substance Challenger Deep";
	/** Theme built-in within JDK */
	public static final String NIMBUS = "Nimbus";
	/**
	 * Theme developed by <a
	 * href="http://code.google.com/p/seaglass/">independent developpers</a>
	 */
	public static final String SEA_GLASS = "Sea Glass (Incubation)";
	/**
	 * Theme developed by <a href="http://www.infonode.net/">NNL Technology
	 * AB</a>
	 */
	public static final String INFO_NODE = "Info Node";
	/**
	 * Theme developed by <a href="http://www.randelshofer.ch/quaqua/">Werner
	 * Randelshofer</a>
	 */
	public static final String QUAQUA = "Quaqua";
	/**
	 * Theme developped by <a
	 * href="http://napkinlaf.sourceforge.net">independent developpers</a>
	 */
	public static final String NAPKIN = "Napkin";
	/**
	 * Theme developped by <a
	 * href="http://www.centigrade.de/en/products/cezanne-look-and-feel-engine">Centigrade</a>
	 */
	public static final String TEXTILE = "Textile";

	/** Convenient list of all theme available */
	public static final String[] INSTALLED_THEMES = new String[] {
			DEFAULT_THEME, SYNTHETICA_BLACK_EYE,
			SUBSTANCE_BUSINESS_BLACK_STEEL, SUBSTANCE_CREME_COFFEE,
			SUBSTANCE_OFFICE_BLUE_2007, SUBSTANCE_CHALLENGER_DEEP, NIMBUS,
			SEA_GLASS, INFO_NODE, QUAQUA, NAPKIN,TEXTILE };

	/** Logger to register useful message coming from this class */
	private static final Logger logger = Logger.getLogger(ThemeManager.class
			.getCanonicalName());

	/** singleton instance */
	private static final ThemeManager instance = new ThemeManager();

	/** Theme dictionary */
	private Map<String, String> themes = new HashMap<String, String>();
	
	/** Component that have to be updated after a theme switch */
	private Set<Component> components = new HashSet<Component>();

	/**
	 * Singleton constructor<br/>
	 * Initialize theme map
	 */
	private ThemeManager() {
		themes.put(DEFAULT_THEME, "javax.swing.plaf.metal.MetalLookAndFeel");
		/*themes.put(SYNTHETICA_BLACK_EYE,
				SyntheticaBlackEyeLookAndFeel.class.getCanonicalName());
		themes.put(SUBSTANCE_BUSINESS_BLACK_STEEL,
				SubstanceBusinessBlackSteelLookAndFeel.class.getCanonicalName());
		themes.put(SUBSTANCE_CREME_COFFEE,
				SubstanceCremeCoffeeLookAndFeel.class.getCanonicalName());
		themes.put(SUBSTANCE_OFFICE_BLUE_2007,
				SubstanceOfficeBlue2007LookAndFeel.class.getCanonicalName());
		themes.put(SUBSTANCE_CHALLENGER_DEEP,
				SubstanceChallengerDeepLookAndFeel.class.getCanonicalName());
		themes.put(NIMBUS, "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
		themes.put(SEA_GLASS, SeaGlassLookAndFeel.class.getCanonicalName());
		themes.put(INFO_NODE, InfoNodeLookAndFeel.class.getCanonicalName());
		themes.put(QUAQUA, Quaqua15LeopardCrossPlatformLookAndFeel.class
				.getCanonicalName());
		themes.put(NAPKIN, NapkinLookAndFeel.class.getCanonicalName());
		themes.put(TEXTILE, TextileLookAndFeel.class.getCanonicalName());*/

		for (Entry<String, String> e : themes.entrySet())
			logger.fine(e.getKey() + " theme class : " + e.getValue());

		String defaultThemeProperty = (String) Application.getInstance()
				.getProperties()
				.get(ApplicationProperties.DEFAULT_THEME_PROPERTY);

		if (defaultThemeProperty != null) {
			logger.log(Level.INFO, "Default theme changed to {0}",
					defaultThemeProperty);
			switchTheme(defaultThemeProperty);
		}
	}

	/**
	 * Singleton access
	 *
	 * @return singleton instance
	 */
	public static ThemeManager getInstance() {
		return instance;
	}

	/**
	 * Switch the UI theme
	 */
	@Override
	public void actionPerformed(ActionEvent e) {
		logger.finer("Action Command : " + e.getActionCommand());
		if (themes.containsKey(e.getActionCommand())) {
			switchTheme(e.getActionCommand());
		} else {
			logger.warning("Asked theme not available : "
					+ e.getActionCommand());
		}
		logger.info("Current theme : " + UIManager.getLookAndFeel().getName());
	}

	/**
	 * Convenient method for switching theme
	 */
	private void switchTheme(String theme) {
		if (themes.get(theme) != null) {

			if (UIManager.getLookAndFeel().getClass().getCanonicalName()
					.equals(themes.get(theme)))
				return;

			logger.log(Level.INFO, "Switch to {0} theme", themes.get(theme)
					.substring(themes.get(theme).lastIndexOf('.') + 1));
			try {
				UIManager.setLookAndFeel(themes.get(theme));
				logger.fine("Theme changed");
				updateComponents();
				logger.fine("Components redrawed");
			} catch (Exception ex) {
				logger.log(Level.SEVERE, "Unable to switch to " + theme
						+ " theme", ex);
			}
		} else
			logger.log(Level.WARNING, theme + " not found !");
	}

	/**
	 * Convenient method for updating UI components
	 */
	private void updateComponents() {
		for (Component comp : components)
			SwingUtilities.updateComponentTreeUI(comp);
	}

	/**
	 * Register UI component that have to be updated
	 *
	 * @param comp
	 *            UI component
	 */
	public void registerUIComponent(Component comp) {
		components.add(comp);
	}

}
