/*
 *  Copyright 2015 Anyware Services
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

/**
 * Menu for selecting a color
 */
Ext.define('Ametys.plugins.skinfactory.widgets.menu.ColorSelectorMenu', {
	extend: 'Ext.menu.Menu',
	
	plain: true,

    /**
     * @private
     * @property {Boolean} _initialized Is the menu initialized?
     */
	_initialized: false,
	
	constructor: function (config)
	{
		config.width = config.width || 175;
		
		this.callParent(arguments);
		
		this.on('afterrender', this._onAfterRender, this);
		
		Ametys.message.MessageBus.on(Ametys.message.Message.MODIFIED, this._onModified, this);
		Ametys.message.MessageBus.on(Ametys.message.Message.LOADED, this._onSkinLoaded, this);
	},
	
	/**
	 * @private
	 * Listener invoked after rendering item.
	 * Apply the parent menu UI to the item
	 */
	_onAfterRender: function()
	{
		if (this.parentMenu && this.parentMenu.ui)
		{
			this.setUI(this.parentMenu.ui);
		}
	},
	
	/**
	 * @private
	 * Listener when the skin was loaded
	 * @param {Ametys.message.Message} message The message from the bus.
	 */
	_onSkinLoaded: function (message)
	{
		var target = message.getTarget(Ametys.message.MessageTarget.SKIN);
        if (target && !this._initialized)
        {
        	Ametys.plugins.skinfactory.skin.SkinDAO.getThemeColors([Ametys.getAppParameter("siteName")], Ext.bind(this._getThemeColorsCb, this));
        	this._initialized = true;
        }
	},
	
	/**
	 * Listener on the modified message. If the skin color theme was changed, update the color selector.
	 * @param {Ametys.message.Message} message The message from the bus.
	 */
	_onModified: function (message)
	{
		var target = message.getTarget(Ametys.message.MessageTarget.SKIN_COLOR_THEME);
		if (target)
		{
			// Color theme changed, refresh this menu
			this.removeAll();
			
			Ametys.plugins.skinfactory.skin.SkinDAO.getThemeColors([Ametys.getAppParameter("siteName")], Ext.bind(this._getThemeColorsCb, this));
		}
	},
	
	/**
	 * @private
	 * Callback avec retrieving the list of theme colors. Load the menu item.
	 * @param {Object[]} themes The list of theme colors
	 */
	_getThemeColorsCb: function (themes)
	{
		var listColors = [];
		var themeId = Ametys.plugins.skinfactory.SkinParametersManager.getCurrentColorTheme();
		
		Ext.Array.each(themes, function (theme) {
			if (theme.id == themeId)
			{
				var colors = theme.colors;
				colors.forEach(function (value, index, array) {
					array[index] = value.toUpperCase();
				});
				
				listColors.push({
					label: "{{i18n PLUGINS_SKINFACTORY_COLORMENU_THEME_COLORS}}",
					colors: theme.colors
				});
				
				this._colors = theme.colors;
			}
		}, this);
		
		listColors.push({
			label: "{{i18n PLUGINS_SKINFACTORY_COLORMENU_DEFAULT_COLORS}}"
		});
		
		var color = Ametys.plugins.skinfactory.SkinParametersManager.getParameterValue(this.getInitialConfig("paramId"));
		
		this.add(Ext.create("Ametys.form.field.ColorSelector", {
			listColors: listColors,
			currentColor: this._formatColorToValue(color),
			allowTransparent: (this.getInitialConfig("allowTransparent") == "false" || this.getInitialConfig("allowTransparent") == false) ? false : true,
			callback: Ext.bind(this._onSelectColor, this)
		}));
	},
	
	/**
	 * @private
	 * Format the color from the skin value into a 6 hexadecimal upper case value.
	 * @param {String} color The color, as stored into the skin.
	 * @return {String} The 6 hexadecimal upper case color code.
	 */
	_formatColorToValue: function (color)
	{
		if (!color)
		{
			return null;
		}
		
		if (/^([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(color))
		{
			color = color.toUpperCase();
		}
		else if (/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(color))
		{
			// Remove '#' character
			color = color.slice(1, 7).toUpperCase();
		}
		else if (Ext.String.startsWith(color, "color-theme-"))
		{
			var index = color.slice("color-theme-".length);
			if (this._colors && this._colors.length > index)
			{
				color = this._colors[index];
			}
		}
		else
		{
			// rgb or rgba value
			color = color.toLowerCase();
		}
		
		// Append zeros if hexa color is too short
		if (/^([A-Fa-f0-9]{1,6})$/.test(color) && color.length < 6)
		{
			color = (color + "000000").slice(0, 6);
		}
		
		return color;
	},
	
	/**
	 * Callback on selecting the color from the color selector. Convert and store the value into the skin
	 * @param {String} color The 6 hexadecimal upper case color code.
	 */
	_onSelectColor: function (color)
	{
		var themeIndex = Ext.Array.indexOf(this._colors || [], color);
		
		if (color != "transparent")
		{
			if (themeIndex > -1)
			{
				color = "color-theme-" + themeIndex;
			}
			else
			{
				if (/^([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(color))
				{
					color = '#' + color;
				}
			}
		}
		
		Ametys.plugins.skinfactory.skin.SkinActions.updateParameter(this.getInitialConfig("paramId"), color.toLowerCase());
	}
	
});