/*
 *  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 controller handles the notification when a page is published, the live preview and the preview
 */
Ext.define(
	'Ametys.plugins.web.page.controller.LivePageController', {
		extend: 'Ametys.web.controller.WebButtonController',
		
		/**
		 * @property {String[]} [_pageIds=[]] List of identifiers of pages concerned by the action of the controller
		 * @private
		 */
        
        /**
         * @property {Boolean} _isContentTarget True if the target message concerns a Content
         * @private
         */
		
		constructor: function(config)
		{
			this._pageIds = [];
            this._isContentTarget = false;
            
			this.callParent(arguments);
			
			// FIXME zoneChanged ? typeChanged ?
			Ametys.message.MessageBus.on(Ametys.message.Message.MODIFIED, this._onModified, this); 
			Ametys.message.MessageBus.on(Ametys.message.Message.WORKFLOW_CHANGED, this._onModified, this);
		},

		/**
		 * @private
		 * Listener for modified or workflow changed messages
		 * Will update the state of the buttons effectively upon the current selection.
		 * @param {Ametys.message.Message} message the message.
		 */
		_onModified: function (message)
		{
			if (this.updateTargetsInCurrentSelectionTargets(message) || message.getTargets(Ametys.message.MessageTarget.CONTENT).length > 0)
			{
                this._isContentTarget = message.getTargets(Ametys.message.MessageTarget.CONTENT).length > 0;
	    		this.refresh();
			}
		},
		
		/**
		 * Get the matching targets that match set link page conditions
		 * @return {Ametys.message.MessageTarget[]} targets filling all conditions.
		 */
		getAllRightPageTargets: function ()
		{
			var matchingTargets = this.getMatchingTargets();
			var me = this;
			
			return Ext.Array.filter (matchingTargets, function (target) {
				return Ext.Array.contains(me._pageIds, target.getParameters().id)
			});
		},
		
		updateState: function()
		{
			this._getStatus(this.getMatchingTargets());
		},

		/**
		 * @private
		 * Get the status
		 * @param targets The page targets
		 */
		_getStatus: function(targets)
		{
            this._calculateStatus(targets, this._getStatusCb);
		},

		/**
         * @private
         * Compute the status of the current page.
         * Done from client-side if the modified target is a page, done from server-side if the modified target is a content
         * @param {Ametys.message.Targets[]} targets The matching page targets
         * @param {Function} callback The callback function to invoked after status was updated
         */
        _calculateStatus: function(targets, callback)
        {
            var result = {
                "invalid-pages": [],
                "allright-pages": [],
                "invalid-page": [],
                "invalid-hierarchy": []
            };
            
            var me = this;
            if (me._isContentTarget)
            {
                // When target message is a content a call to server side is needed to update the page status
                var remainingPagesCounter = targets.length;
                Ext.Array.each(targets, function(matchingTarget){
                    
                    var pageId = matchingTarget.getParameters().id;
                    
                    Ametys.web.page.PageDAO.getPage(pageId, function(page){
                        
                        me._updatePageStatus(matchingTarget, page, result);
                        
                        remainingPagesCounter--;
                        if (remainingPagesCounter == 0)
                        {
                            callback.apply(me, [result]);
                        }
                    });
                });
            }
            else
            {
                // Update status from page target (done from client-side only)
                Ext.Array.each(targets, function(matchingTarget){
                    var parameters = matchingTarget.getParameters();
                    if (parameters && parameters.page)
	                {
	                    me._updatePageStatus(matchingTarget, parameters.page, result);
	                }
                });
                
                callback.apply(me, [result]);
            }
        },
        
        /**
         * @protected
         * Update the page status
         * @param {Ametys.message.MessageTarget} matchingTarget The matching page target
         * @param {Ametys.web.page.Page} page The page associated to this target (should be up-to-date)
         * @param {Object} result The status result to be updated
         */
        _updatePageStatus: function(matchingTarget, page, result)
        {
            var error = false;

            if (!this.hasRightOnAny([matchingTarget]))
            {
                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);
                error = true;
            }

            var validPage = page.getIsPageValid();
            if (!validPage)
            {
                var i18nStr = this.getConfig("invalid-page-description");
                var description = Ext.String.format(i18nStr, page.getTitle());
                var pageParam = this._getPageDefaultParameters(page);
                pageParam["description"] = description;
                result["invalid-pages"].push(pageParam);
                error = true;
            }
            else if (validPage && !page.getIsLiveHierarchyValid())
            {
                var i18nStr = this.getConfig("invalid-hierarchy-description");
                var description = Ext.String.format(i18nStr, page.getTitle());
                var pageParam = this._getPageDefaultParameters(page);
                pageParam["description"] = description;
                result["invalid-hierarchy"].push(pageParam);
                error = true;
            }

            if (!error)
            {
                var i18nStr = this.getConfig("allright-page-description");
                var description = Ext.String.format(i18nStr, page.getTitle());
                var contentParam = this._getPageDefaultParameters(page);
                contentParam["description"] = description;
                result["allright-pages"].push(contentParam);
            }
        },
        
        /**
         * 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;
        },
        
		/**
		 * Callback for the button reloading process
		 * @param {Object} params the server's response
		 * @param {Object[]} params.allright-pages the allright pages
		 * @param {Object[]} params.invalid-hierarchy the pages having an invalid hierarchy
		 * @param {Object[]} params.invalid-pages the invalid pages
		 */
		_getStatusCb: function(params)
		{
			var allRightPages = params['allright-pages'];
			if (allRightPages.length > 0)
			{
				for (var i=0; i < allRightPages.length; i++)
				{
					this._pageIds.push(allRightPages[i].id);
				}
				this.enable();
			}
			else
			{
				this.disable();
			}
			
			this._updateTooltipDescription(this.getInitialConfig('default-description'), params);
		},
		
		/**
		 * @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, "noright", params['noright-pages']);
			description = this._handlingMultiple(description, "invalid-page", params['invalid-pages']);
			description = this._handlingMultiple(description, "invalid-hierarchy", params['invalid-hierarchy']);
			description = this._handlingMultiple(description, 'allright-page', params['allright-pages']);
			
			this.setDescription (description);
		},
		
		/**
		 * Generates the tooltip to set 
		 * @param {String} description the description where to add text in html
		 * @param {String} paramPrefix the parameter prefix
		 * @param {Object} pages the pages 
		 */
		_handlingMultiple: function(description, paramPrefix, pages)
		{
			if (pages && pages.length > 0)
			{
				if (description != "")
				{
					description += "<br/><br/>";
				}
				
				description += this.getInitialConfig(paramPrefix + "-start-description");
				for (var i=0; i < pages.length; i++)
				{
					if (i != 0) 
					{
						description += ", ";
					}
					description += pages[i].description;
				}
				description += this.getInitialConfig()[paramPrefix + "-end-description"];
			}
			
			return description;
		}
	}
);