/*
 *  Copyright 2014 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.
 */

/**
 * Singleton class to handle actions on tags.
 * @private
 */
Ext.define('Ametys.plugins.web.tag.AffectTagAction', {
    singleton : true,

    /**
     * Function called to affect a tag on pages and contents
     * @param {Ametys.ribbon.element.ui.ButtonController/String[]} controller The controller calling the function or list of pages ID where tags will be affected
     * @param {String[]} contentIds IDs of contents to affect
     * @param {Function} [callback] Function to call after affectation
     */
    affect: function (controller, contentIds, callback)
    {
        var pageIds = controller;
        if (controller != null && controller.isButtonController)
        {
            var targets = controller.getAllRightTargets();
            if (targets.length > 0)
            {
                contentIds = this._convertToIds (targets, Ametys.message.MessageTarget.CONTENT);
                pageIds = this._convertToIds (targets, Ametys.message.MessageTarget.PAGE);
            }
        }

        if (Array.isArray(pageIds) && pageIds.length > 0)
            {
                Ametys.data.ServerComm.callMethod({
                    role: "org.ametys.web.repository.page.PageDAO", 
                    methodName: 'getTags', 
                    parameters: [ pageIds ],
                    waitMessage: true,
                    callback: {
                        handler: this._getPageTagsCb,
                        scope: this,
                        arguments: {
                            contentIds: contentIds,
                            pageIds: pageIds,
                            callback: callback
                        }
                    }
                });
            }
            else if (contentIds.length > 0)
            {
                Ametys.data.ServerComm.callMethod({
                    role: "org.ametys.cms.repository.ContentDAO", 
                    methodName: 'getTags', 
                    parameters: [ contentIds ],
                    waitMessage: true,
                    callback: {
                        handler: this._getContentTagsCb,
                        scope: this,
                        arguments: {
                            tags: [],
                            contentIds: contentIds,
                            pageIds: [],
                            callback: callback
                        }
                    }
                });
            }
    },
    
    /**
     * @private
     * Callback invoked after retrieving tags of selected pages
     * @param {String[]} pageTags the tags affected to pages
     * @param {Object} args the callback arguments:
     * @param {String[]} args.contentIds the ids of selected contents
     * @param {String[]} args.pageIds the ids of selected pages
     */
    _getPageTagsCb: function (pageTags, args)
    {
    	var contentIds = args.contentIds;
    	if (contentIds.length > 0)
    	{
    		Ametys.data.ServerComm.callMethod({
                role: "org.ametys.cms.repository.ContentDAO", 
                methodName: 'getTags', 
                parameters: [ contentIds ],
                waitMessage: true,
                callback: {
                    handler: this._getContentTagsCb,
                    scope: this,
                    arguments: {
                    	tags: pageTags,
                    	contentIds: args.contentIds,
                    	pageIds: args.pageIds,
                        callback: args.callback
                    }
                }
            });
    	}
    	else
    	{
    		this._selectTags (args.pageIds, [], pageTags, args.callback);
    	}
    },
    
    /**
     * @private
     * Callback invoked after retrieving tags of selected contents
     * @param {String[]} contentTags the tags affected to contents
     * @param {Object} args the callback arguments:
     * @param {String[]} args.tags the tags of selected contents
     * @param {String[]} args.contentIds the ids of selected contents
     * @param {String[]} args.pageIds the ids of selected pages
     */
    _getContentTagsCb: function (contentTags, args)
    {
    	// Merge pages and contents' tags
    	var tags = Ext.Array.merge(contentTags, args.tags);
    	
    	this._selectTags (args.pageIds, args.contentIds, tags, args.callback);
    },

    /**
     * @private
     * Open dialog box to select tags
     * @param {String[]} pageIds The id of pages to be tagged
     * @param {String[]} contentIds The id of contents to be tagged
     * @param {String[]} tags The current tags
     * @param {Function} [callback] Function to invoked updating tags
     */
    _selectTags: function (pageIds, contentIds, tags, callback)
    {
		Ametys.cms.uihelper.ChooseTag.open({
            values: tags,
            taggableObjects: Ext.Array.merge(pageIds, contentIds),
            
            plugin: "web",
            url: "tags.json",
            
            multiple: true,
            filterTarget: contentIds.length == 0 ? 'CONTENT' : (pageIds.length == 0 ? 'PAGE' : null),
            		
            callback: Ext.bind(this._doAffect, this, [pageIds, contentIds, callback], 2)
        });
    },

    /**
     * @private
     * Affect the tags that were selected by the helper
     * @param  {String[]} tagNames The list of tags to assign
     * @param {Object} params The callback arguments
     * @param {String[]} pageIds The id of pages to be tagged
     * @param {String[]} contentIds The id of contents to be tagged
     * @param {Function} [callback] Function to invoked updating tags
     */
    _doAffect: function(tagNames, params, pageIds, contentIds, callback)
    {
        // Set the selected tags on REPLACE mode.
        Ametys.web.page.PageDAO.tag([pageIds, contentIds, tagNames, Ametys.getAppParameters()], callback, {
            waitMessage: "{{i18n PLUGINS_WEB_CREATEPAGE_TAGS_WAITING_MSG}}",
            errorMessage: true
        });
    },
    
    /**
     * @private
     * Get the ids from a list of message targets
     * @param  {Ametys.message.MessageTarget[]} targets list of targets
     * @param  {String} type The type of target to filter by.
     * @return {String[]} the ids
     */
    _convertToIds: function (targets, type)
    {
        var ids = [];
        
        Ext.Array.forEach (targets, function (target) {
        	if (target != null && target.getId() == type)
        	{
        		ids.push(target.getParameters().id);
        	}
        });
        
        return ids;
    }
});