/*
 *  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.
 */
/**
 * This class controls a ribbon button that allows to set the visibility of a page.<br/>
 * The button is toggle if page is currently invisible.
 * @private
 */
Ext.define('Ametys.plugins.web.page.controller.PageVisibilityController', {
	extend: 'Ametys.web.controller.WebButtonController',
		
	/**
	 * @private
	 * @property {String[]} _pageIds The id the currently selected pages
	 */
	/**
	 * @private
	 * @property {String[]} _visiblePageIds The ids of visible pages among the current selection
	 */
	/**
	 * @private
	 * @property {String[]} _invisiblePageIds The ids of invisible pages among the current selection
	 */
	
	/**
	 * @cfg {String} [icon-glyph] The CSS class for button's icon when the page is visible
	 */
    /**
     * @cfg {String} [invisible-icon-glyph] The CSS class for button's icon when the page is invisible
     */
	
	constructor: function(config)
	{
		this.callParent(arguments);
		
		Ametys.message.MessageBus.on(Ametys.message.Message.MODIFIED, this._onModified, this);
	},
	
	/**
	 * Listener handler for modified messages
	 * @param {Ametys.message.Message} message the message
	 */
	 _onModified: function(message)
	 { 
		 if (this.updateTargetsInCurrentSelectionTargets (message))
		 {
			 this.refresh();
		 }
	 },
	 
	 updateState: function()
	 {
		this._getStatus(this.getMatchingTargets());
	 },
	
	/**
	 * Returns the ids of pages currently visible among the current selection
	 * @return {String[]} The pages' id
	 */
	getVisiblePageIds: function ()
	{
		return this._visiblePageIds;
	},
	
	/**
	 * Returns the ids of pages currently invisible among the current selection
	 * @return {String[]} The pages' id
	 */
	getInvisiblePageIds: function ()
	{
		return this._invisiblePageIds;
	},
	
	/**
	 * @private
	 * Get the status
	 * @param targets The page targets
	 */
	_getStatus: function (targets)
	{
		this.disable();
		
		this._pageIds = [];
		this._invisiblePageIds = [];
		this._visiblePageIds = [];
		
        var result = this._calculateStatus(targets);
        this._getStatusCb(result);
	},

    /**
     * @protected
     * Simulation of getStatus server side, done only client-side.
     * @param {Object[]} pageTargets see Ametys.ribbon.element.ui.CommonController#getMatchingTargets
     * @return {Object} a map of arrays representing contents in different states. nomodifiable-pages, noright-pages, invisible-pages, parent-invisible-pages, visible-pages
     */
    _calculateStatus: function(pageTargets)
    {
        var result = {};
        result["nomodifiable-pages"] = [];
        result["noright-pages"] = [];
        result["invisible-pages"] = [];
        result["parent-invisible-pages"] = [];
        result["visible-pages"] = [];

        Ext.Array.each(pageTargets, function(pageTarget)
            {
                var parameters = pageTarget.getParameters();
                if (parameters && parameters.page)
                {
                    var page = parameters.page;
                    if (!page.getIsModifiable())
                    {
                        var i18nStr = this.getConfig("nomodifiable-page-description");
                        var description = Ext.String.format(i18nStr, page.getTitle());
                        var pageParam = this._getPageDefaultParameters(page);
                        pageParam["description"] = description;
                        result["nomodifiable-pages"].push(pageParam);
                    }
                    else if (!this.hasRightOnAny([pageTarget]))
                    {
                        var i18nStr = this.getConfig("noright-page-description");
                        var description = Ext.String.format(i18nStr, page.getTitle());
                        var pageParam = this._getPageDefaultParameters(page);
                        pageParam["description"] = description;
                        result["noright-pages"].push(pageParam);
                    }
                    else
                    {
                        if (!page.getIsVisible())
                        {
                            var i18nStr = this.getConfig("page-invisible-description");
                            var description = Ext.String.format(i18nStr, page.getTitle());
                            var pageParam = this._getPageDefaultParameters(page);
                            pageParam["description"] = description;
                            result["invisible-pages"].push(pageParam);
                        }
                        else if (page.getIsParentInvisible())
                        {
                            var i18nStr = this.getConfig("page-parent-invisible-description");
                            var description = Ext.String.format(i18nStr, page.getTitle());
                            var pageParam = this._getPageDefaultParameters(page);
                            pageParam["description"] = description;
                            result["parent-invisible-pages"].push(pageParam);
                        }
                        else
                        {
                            var i18nStr = this.getConfig("page-visible-description");
                            var description = Ext.String.format(i18nStr, page.getTitle());
                            var pageParam = this._getPageDefaultParameters(page);
                            pageParam["description"] = description;
                            result["visible-pages"].push(pageParam);
                        }
                    }
                }
            }, this);
        return result;
    },
	
	/**
	 * Callback for the button reloading process
	 * @param {Object} params the server's response
     * @param {String[]} params.invisible-pages The invisible pages identifier
     * @param {String[]} params.visible-pages The visible pages identifier
     * @param {String[]} params.parent-invisible-pages The invisible parents of visible pages
	 */
	_getStatusCb: function(params)
	{
		this._updateTooltipDescription(this.getInitialConfig('description'), params);
		this._updateIcons(params);
		
		var me = this;
		Ext.Array.each (params['invisible-pages'], function (page) {
			me._pageIds.push(page.id);
			me._invisiblePageIds.push(page.id);
		});
		
		Ext.Array.each (params['visible-pages'], function (page) {
			me._pageIds.push(page.id);
			me._visiblePageIds.push(page.id);
		});
		
		var nbParentInvisiblePages = params['parent-invisible-pages'].length;
		this.toggle(this._invisiblePageIds.length > 0 || nbParentInvisiblePages > 0);
        
        var disabled = this._isDisabled(params);
		this.setDisabled(disabled);
	},
	
	/**
	 * @protected
	 * Update the tooltip description according state of the current selection
	 * @param description The initial description. Can be empty.
	 * @param params The JSON result received
	 */
	_updateTooltipDescription: function (description, params)
	{
		description = this._handlingMultiple (description, 'page-visible', params['visible-pages']);
		description = this._handlingMultiple(description, "page-invisible", params['invisible-pages']);
		description = this._handlingMultiple(description, "page-parent-invisible", params['parent-invisible-pages']);
		description = this._handlingMultiple(description, "nomodifiable", params['nomodifiable-pages']);
		description = this._handlingMultiple(description, "noright", params['noright-pages']);
		
		this.setDescription (description);
	},
	
	/**
	 * @private
	 * Add text to description
	 * @param description The initial description to concatenate. Can be empty.
	 * @param {String} prefix The parameters prefix to used to retrieve the start and end description. The start and end description are retrieved from initial configuration with [prefix]-start-description and [prefix]-end-description
	 * @param {Object[]} pages The concerned pages. If empty, no text will be concatenated
	 */
	_handlingMultiple: function(description, prefix, pages)
	{
		if (pages.length > 0)
		{
			if (description != "")
			{
				description += "<br/><br/>";
			}
			
			description += this.getInitialConfig(prefix + "-start-description");
			for (var i=0; i < pages.length; i++)
			{
				if (i != 0) 
				{
					description += ", ";
				}
				description += pages[i].description;
			}
			description += this.getInitialConfig(prefix + "-end-description");
		}
		
		return description;
	},
	
	/**
     * @private
	 * Update the icons of the button
	 * @param {Object} params the server's parameters
	 */
	_updateIcons: function(params)
	{
		var nbVisiblePages = params['visible-pages'].length;
		var nbInvisiblePages = params['invisible-pages'].length;
		var nbParentInvisiblePages = params['parent-invisible-pages'].length;
		
		var iconGlyph = this.getInitialConfig()['icon-glyph'];
		
		if (nbVisiblePages > 0 && nbInvisiblePages == 0 && nbParentInvisiblePages == 0)
		{
            iconGlyph = this.getInitialConfig()['icon-glyph'];
		}
		
		if (nbInvisiblePages > 0 || nbParentInvisiblePages > 0)
		{
			iconGlyph = this.getInitialConfig()['invisible-icon-glyph'];
		}
        
        this.setGlyphIcon(iconGlyph);
	},
    
    /**
     * @private
     * Determines if the controller has to be disabled
     * @param {Object} params the server's parameters
     * @return {Boolean} if the controller has to be disabled
     */
    _isDisabled: function (params)
    {
        var nbVisiblePages = params['visible-pages'].length;
	    var nbInvisiblePages = params['invisible-pages'].length;
	    var nbParentInvisiblePages = params['parent-invisible-pages'].length;
	    var nbNorightsPages = params['noright-pages'].length;
	    
	    return (nbVisiblePages == 0 && nbInvisiblePages == 0 && nbParentInvisiblePages > 0) || nbNorightsPages > 0;
    },

    /**
     * create a json object representing a page
     * @private
     * @param {Ametys.web.page.Page} page The page to analyse
     * @return {Object} containing id and title
     */
    _getPageDefaultParameters : function(page)
    {
        var pageParams = {};
        pageParams["id"] = page.getId();
        pageParams["title"] = page.getTitle();
        return pageParams;
    }
});