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

/**
 * CRUD actions on queries
 * @private
 */
Ext.define('Ametys.plugins.queriesdirectory.actions.QueriesActions', {
	singleton: true,
    
    /**
     * Save the query
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The button controller calling this function
     */
    saveAsQuery: function (controller)
    {
        var tool = Ametys.tool.ToolsManager.getFocusedTool();
        
        if (tool && tool.getCurrentSearchParameters)
        {
            var content = Ext.JSON.encode({
                toolId: tool.getFactory().getId(),
                toolParams: tool.getCurrentSearchParameters(),
                exportParams: tool.getSearchParametersForExport(),
                exportXMLUrl: tool.getExportXMLUrl(),
                exportXMLUrlPlugin: tool.getExportXMLUrlPlugin()
            });
            
            var type = this._getType(tool);
            
            var me = this;
            Ametys.plugins.queriesdirectory.helper.ChooseQuery.act({
                iconCls: 'ametysicon-save31',
                title: controller.getInitialConfig()['label'],
                helpMessage: "{{i18n PLUGINS_QUERIESDIRECTORY_SAVE_AS_HINT}}",
                params: {content: content, tool: tool, queryId: tool.getParams().queryId},
                type: type,
                value: tool.getParams().queryId,
                showConfirm: true,
                chooseQueryCallback: Ext.bind (Ametys.plugins.queriesdirectory.actions.QueriesActions._saveQueryCb, Ametys.plugins.queriesdirectory.actions.QueriesActions, [tool, type], true),
                allowCreation: true,
                createCallback: function (response) {
                    if (Ametys.tool.ToolsManager.getTool('uitool-queries') == null)
                    {
                        Ametys.tool.ToolsManager.openTool('uitool-queries', {});
                    }
                    me._onSave(response, {
                            tool: tool
                    })
                }
            });
      
        }
    },

    /**
     * Save the query as a new query
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The button controller calling this function
     */
    saveQuery: function (controller)
    {
        var tool = Ametys.tool.ToolsManager.getFocusedTool();

        if (tool && tool.getCurrentSearchParameters)
        {
	        var content = Ext.JSON.encode({
	            toolId: tool.getFactory().getId(),
	            toolParams: tool.getCurrentSearchParameters(),
	            exportParams: tool.getSearchParametersForExport(),
	            exportXMLUrl: tool.getExportXMLUrl(),
	            exportXMLUrlPlugin: tool.getExportXMLUrlPlugin()
	        });
	        
            var type = this._getType(tool);
            
            if (!tool.getParams().queryId || tool.getParams().readOnly)
            {
	            // there is no current query, or current query can't be edited, display form to create a new one
                var me = this;
                Ametys.plugins.queriesdirectory.helper.CreateOrEditQuery.act({
                    mode: 'new',
                    title: controller.getInitialConfig()['label'],
                    type: type,
                    params: {content: content},
                    callback: function (response) {
                        if (Ametys.tool.ToolsManager.getTool('uitool-queries') == null)
                        {
                            Ametys.tool.ToolsManager.openTool('uitool-queries', {});
                        }
                        me._onSave(response, {tool: tool});
                    }
                });
            }
            else
            {
	             // current query already exist, just save it
                 Ametys.plugins.queriesdirectory.QueriesDAO.saveQuery(
                     [tool.getParams().queryId, type, content], 
                     this._onSave, 
                     {
                         arguments: 
                             {
                                 tool: tool
                             }
                     });
            }
        }
    },
    
    /**
     * @private
     * Get the type of query depending on the current tool
     * @param {Ametys.tool.Tool} tool The search tool
     * @return {String} The type of query
     */
    _getType: function(tool)
    {
        try
        {
            if (tool instanceof Ametys.plugins.cms.search.solr.SolrContentSearchTool)
            {
                return Ametys.plugins.queriesdirectory.model.SolrQuery.QUERY_TYPE;
            }
        }
        catch (e)
        {
            // SolrContentSearchTool not loaded
        }
        
        try
        {
            if (tool instanceof Ametys.plugins.cms.search.ScriptTool)
            {
                return Ametys.plugins.queriesdirectory.model.ScriptQuery.QUERY_TYPE;
            }
        }
        catch (e)
        {
            // ScriptTool not loaded
        }
        
        return Ext.isFunction(tool.isAdvancedMode) && tool.isAdvancedMode() ? Ametys.plugins.queriesdirectory.model.AdvancedQuery.QUERY_TYPE : Ametys.plugins.queriesdirectory.model.SimpleQuery.QUERY_TYPE; 
    },

	/**
	 * This action edits the selected query
	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 */
	editQuery: function(controller)
	{		
		var targets = controller.getMatchingTargets();
		
		if (targets.length > 0)
		{
            Ametys.plugins.queriesdirectory.helper.CreateOrEditQuery.act({
                mode: 'edit',
                type: targets[0].getParameters().type,
                params: targets[0].getParameters()
            });
		}	
	},
	
	/**
	 * Delete the selected queries
	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 */
	deleteQuery: function(controller)
	{
		var targets = controller.getMatchingTargets();
		
		if (targets.length > 0)
		{
			Ametys.Msg.confirm("{{i18n PLUGINS_QUERIESDIRECTORY_DELETE_QUERY_TITLE}}", 
					"{{i18n PLUGINS_QUERIESDIRECTORY_DELETE_QUERY_CONFIRM}}", 
					function(btn) {
						if(btn == 'yes')
						{
							this._doDelete(targets);
						}
						
					},
					this);
		}
		
	},
    
    /**
     * Creates a new queries directory under the selected one
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
     */
    createQueryContainer: function(controller)
    {
        var target = Ametys.message.MessageTargetHelper.findTarget(controller.getMatchingTargets(), Ametys.message.MessageTarget.QUERY_CONTAINER);
        if (!target)
        {
            return;
        }
        
        var targetParameters = target.getParameters(),
            parentId = targetParameters.id;
            
        Ametys.plugins.queriesdirectory.QueriesDAO.createQueryContainer([parentId, "{{i18n PLUGINS_QUERIESDIRECTORY_CREATE_CONTAINER_DEFAULT_NAME}}"]);
    },
    
    /**
     * Rename the selected queries directory
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
     */
    renameQueryContainer: function(controller)
    {
        var target = Ametys.message.MessageTargetHelper.findTarget(controller.getMatchingTargets(), Ametys.message.MessageTarget.QUERY_CONTAINER);
        if (!target)
        {
            return;
        }
        
        var targetParameters = target.getParameters(),
            id = targetParameters.id,
            currentName = targetParameters.name;
        function _doRename(newName)
        {
            if (currentName != newName)
            {
                Ametys.plugins.queriesdirectory.QueriesDAO.renameQueryContainer([id, newName]);
            }
        }
        
        if (id == 'root')
        {
            return;
        }
        
        Ametys.Msg.prompt(
            "{{i18n PLUGINS_QUERIESDIRECTORY_RENAME_CONTAINER_PROMPT_TITLE}}",
            "{{i18n PLUGINS_QUERIESDIRECTORY_RENAME_CONTAINER_PROMPT_FIELD_NAME}}",
            function(btn, text) {
                if (btn == 'ok')
                {
                    _doRename(text);
                }
            },
            this,
            false,
            currentName
        );
    },
    
    /**
     * Delete the selected queries directories
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
     */
    deleteQueryContainer: function(controller)
    {
        var targets = controller.getMatchingTargets();
        var ids = Ext.Array.map(targets, function(target) {
            return target.getParameters().id;
        });
        
        if (targets.length > 0)
        {
            Ametys.plugins.queriesdirectory.QueriesDAO.mustWarnBeforeDeletion([ids], promptConfirm);
        }
        
        function promptConfirm(mustWarn)
        {
            var msg = "{{i18n PLUGINS_QUERIESDIRECTORY_DELETE_CONTAINER_CONFIRM}}" + (mustWarn ? "{{i18n PLUGINS_QUERIESDIRECTORY_DELETE_CONTAINER_CONFIRM_WARN}}" : "");
            Ametys.Msg.show({
                title: "{{i18n PLUGINS_QUERIESDIRECTORY_DELETE_CONTAINER_TITLE}}", 
                msg: msg, 
                buttons: Ext.Msg.YESNO,
                icon: mustWarn ? Ext.MessageBox.WARNING : Ext.MessageBox.QUESTION,
                fn: function(btn) {
                    if(btn == 'yes')
                    {
                        doDelete();
                    }
                },
                scope: this
            });
        }
        
        function doDelete()
        {
            Ametys.plugins.queriesdirectory.QueriesDAO.deleteQueryContainer([ids]);
        }
    },
	
	/**
	 * This action execute the selected query
	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 */
	executeQuery: function(controller)
	{		
		this._getQueryFromTarget(controller.getMatchingTargets(), function (query) {
            query.execute();
        });
	},
	
	/**
	 * This action open and execute the selected query
	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 */
	openQuery: function(controller)
	{		
        this._getQueryFromTarget(controller.getMatchingTargets(), function (query) {
            query.open();
        });
	},
	
    /**
     * Get the query for the selection targets, 
     * @param {Ametys.message.MessageTarget[]} targets The targets
     * @param {Function} callback Callback that will receive the query
     * @private
     */
    _getQueryFromTarget: function(targets, callback)
    {
        if (targets && targets.length > 0)
        {
            Ametys.plugins.queriesdirectory.QueriesDAO.getQuery(targets[0].getParameters().id, function (q) {
                var query = Ametys.plugins.queriesdirectory.model.QueryFactory.create(q.getType(), q.getId(), q.getContent(), q.getTitle(), !q.getCanWrite());
                var selection = targets[0].getParameters().selection;
                if (selection)
                {
                    Ext.create("Ametys.message.Message", {
                        type: Ametys.message.Message.SELECTION_CHANGED,
                        targets: selection,
                        callback: function() {
                            callback(query);
                        }
                    });
                }
                else
                {
                    callback(query);
                }
            });
        }
    },

	/**
	 * Callback function invoked after the #deleteQuery confirm box is validated
	 * @param {Ametys.message.MessageTarget[]} targets The queries targets
	 * @private
	 */
	_doDelete: function (targets)
	{
        var ids = Ext.Array.map(targets, function(target) {
            return target.getParameters().id;
        });
        
        Ametys.plugins.queriesdirectory.QueriesDAO.deleteQuery([ids]);
	},
	
	/**
	 * Update the query
	 * @param {String} queryId The query id
     * @param {String} content The content of the query
	 * @param {Object} tool The search tool
	 * @param {String} type The type of query
	 * @private
	 */
	_saveQueryCb: function (response, tool, type)
	{
        var oldQueryId = tool.getParams().queryId;
        
        if (response.id != oldQueryId)
        {
            // If the tool of chosen query is open, it should be closed.
            var existingTool = Ametys.tool.ToolsManager.getTool(tool.getFactory().getId() + "$" + response.id)
            if (existingTool != null)
            {
                existingTool.close();
            }
        }
        
        Ametys.plugins.queriesdirectory.QueriesDAO.saveQuery([response.id, type, response.content], 
                this._onSave, 
                {arguments: {tool: tool}});
	},

    /**
     * Callback of {@link #_ok} function
     * @param {Object} response The server response
     * @param {Array} params The server call parameters
     * @private
     */
    _onSave: function(response, params)
    {
        if (response.id)
        {
            var tool = params.tool;
            var currentToolId = tool.getId()
            var toolFactory = tool.getFactory();
            
            var toolId = tool.getFactory().getId() + "$" + response.id;
            if (currentToolId != toolId && toolFactory instanceof Ametys.tool.factory.BasicToolFactory && toolFactory.getInitialConfig().generateIdIfNotSpecified)
            {
                // Update tool identifier
                tool = Ametys.tool.ToolsManager.changeToolIdentifier(currentToolId, toolId);
            }
            
            var content = Ext.JSON.decode(response.content);
            // Update tool params
            var toolParams = Ext.applyIf(content.toolParams, tool.getParams());
            toolParams.queryId = response.id;
            Ametys.tool.Tool.prototype.setParams.apply(tool, [toolParams]); // avoid tool refreshing
            
            tool.setDirty(false);
            
            Ametys.notify({
                type: 'info',
                title: "{{i18n PLUGINS_QUERIESDIRECTORY_SAVE_DIALOG_TITLE}}",
                description: "{{i18n PLUGINS_QUERIESDIRECTORY_SAVE_DIALOG_TITLE_SUCCESS}}"
            });
        }
        else
        {
            Ametys.notify({
                type: 'warn',
                title: "{{i18n PLUGINS_QUERIESDIRECTORY_SAVE_DIALOG_TITLE}}",
                description: "{{i18n PLUGINS_QUERIESDIRECTORY_SAVE_DIALOG_TITLE_ERROR}}"
                
            });
        }
    },
    
    /**
     * Callback of {@link #_ok} function
     * @param {Object} response The server response
     * @param {Array} params The server call parameters
     * @private
     */
    _onSaveFormatting: function(response, params)
    {
        if (response.id)
        {
            var tool = params.tool;
            
            // Update tool params
            var toolParams = tool.getParams();
            toolParams.formattingQueryId = response.id;
            Ametys.tool.Tool.prototype.setParams.apply(tool, [toolParams]); // avoid tool refreshing
                        
            Ametys.notify({
                type: 'info',
                title: "{{i18n PLUGINS_QUERIESDIRECTORY_SAVE_FORMATTING_DIALOG_TITLE}}",
                description: "{{i18n PLUGINS_QUERIESDIRECTORY_SAVE_FORMATTING_DIALOG_TITLE_SUCCESS}}"
            });
        }
        else
        {
            Ametys.notify({
                type: 'warn',
                title: "{{i18n PLUGINS_QUERIESDIRECTORY_SAVE_FORMATTING_DIALOG_TITLE}}",
                description: "{{i18n PLUGINS_QUERIESDIRECTORY_SAVE_FORMATTING_DIALOG_TITLE_ERROR}}"
                
            });
        }
    },
        
    /**
     * Save and replace the current formatting of the query, or create a new one if none exists
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The button controller calling this function
     */
    saveFormatting: function (controller)
    {
        var tool = Ametys.tool.ToolsManager.getFocusedTool();
        
        if (tool)
        {
            if (!tool.getParams().formattingQueryId)
            {
                // there is no current formatting query
                var tool = Ametys.tool.ToolsManager.getFocusedTool();
                
                if (tool && tool.getCurrentFormatting)
                {
                    var content = Ext.JSON.encode({
                        toolId: tool.getFactory().getId(),
                        toolTitle: tool.getTitle(),
                        formatting: tool.getCurrentFormatting()
                    });

                    var me = this;
                    Ametys.plugins.queriesdirectory.helper.CreateOrEditQuery.act({
                        mode: 'new',
                        title: controller.getInitialConfig()['label'],
                        type: Ametys.plugins.queriesdirectory.model.QueryFormatting.FORMATTING_TYPE,
                        params: {content: content},
                        callback: function (response) {
                            if (Ametys.tool.ToolsManager.getTool('uitool-queries') == null)
                            {
                                Ametys.tool.ToolsManager.openTool('uitool-queries', {});
                            }
                            me._onSaveFormatting(response, {tool: tool});
                        }
                    });
                }
            }
            else if (tool.getCurrentFormatting)
            {
                Ametys.plugins.queriesdirectory.QueriesDAO.getQuery(tool.getParams().formattingQueryId, Ext.bind(this._saveFormatting, this, [controller], 1))
            }
        }
    },

    /**
     * Save and replace the current formatting of the query
     * @param Object formattingQuery The formatting query to save
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The button controller calling this function
     * @private
     */
    _saveFormatting: function (formattingQuery, controller)
    {
        var tool = Ametys.tool.ToolsManager.getFocusedTool();

        if (formattingQuery == null)
        {
            // Query does not exist anymore
            var toolParams = tool.getParams();
            delete toolParams.formattingQueryId;
            Ametys.tool.Tool.prototype.setParams.apply(tool, [toolParams]); // avoid tool refreshing
            this.saveFormatting(controller);
        }
        else
        {
            var me = this;
            Ametys.Msg.confirm("{{i18n PLUGINS_QUERIESDIRECTORY_SAVE_AS_CONFIRM_TITLE}}", 
                    Ext.String.format("{{i18n PLUGINS_QUERIESDIRECTORY_SAVE_AS_CONFIRM_FORMATTING_TEXT}}", formattingQuery.getTitle()), 
                    function(btn) {
                if(btn == 'yes')
                {
                    var content = Ext.JSON.encode({
                        toolId: tool.getFactory().getId(),
                        toolTitle: tool.getTitle(),
                        formatting: tool.getCurrentFormatting()
                    });
                    
                    var type = Ametys.plugins.queriesdirectory.model.QueryFormatting.FORMATTING_TYPE;
                    
                    
                    Ametys.plugins.queriesdirectory.QueriesDAO.saveQuery(
                            [tool.getParams().formattingQueryId, type, content], 
                            me._onSaveFormatting, 
                            {
                                arguments: 
                                {
                                    tool: tool
                                }
                            });
                }
                
            },
            this);
        }
    },
        
    /**
     * Save the formatting of the query
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The button controller calling this function
     */
    saveFormattingAs: function (controller)
    {
        var tool = Ametys.tool.ToolsManager.getFocusedTool();
        var content = Ext.JSON.encode({
            toolId: tool.getFactory().getId(),
            toolTitle: tool.getTitle(),
            formatting: tool.getCurrentFormatting()
        });
        var type = Ametys.plugins.queriesdirectory.model.QueryFormatting.FORMATTING_TYPE;

        var me = this;
        Ametys.plugins.queriesdirectory.helper.ChooseQuery.act({
                    iconCls: 'ametysicon-save31',
                    title: controller.getInitialConfig()['label'],
                    helpMessage: "{{i18n PLUGINS_QUERIESDIRECTORY_SAVE_AS_HINT}}",
                    linkText: "{{i18n PLUGINS_QUERIESDIRECTORY_DIALOG_CHOOSEQUERY_ADDFORMATTING}}",
                    params: {content: content},
                    type: type,
                    value: tool.getParams().formattingQueryId,
                    showConfirm: true,
                    confirmText: "{{i18n PLUGINS_QUERIESDIRECTORY_SAVE_AS_CONFIRM_FORMATTING_TEXT}}",
                    allowCreation: true,
                    createCallback: function (response) {
                        if (Ametys.tool.ToolsManager.getTool('uitool-queries') == null)
                        {
                            Ametys.tool.ToolsManager.openTool('uitool-queries', {});
                        }
                        me._onSaveFormatting(response, {
                                tool: tool
                        })
                    },
                    chooseQueryCallback: function (response) {
                        if (Ametys.tool.ToolsManager.getTool('uitool-queries') == null)
                        {
                            Ametys.tool.ToolsManager.openTool('uitool-queries', {});
                        }
                        me._onSaveFormatting(response, {
                                tool: tool
                        })
                    }
                });
         
        
    },
    
    applyFormatting: function(controller)
    {
        var tool = Ametys.tool.ToolsManager.getFocusedTool();
        
        var me = this;
        Ametys.plugins.queriesdirectory.helper.ChooseQuery.act({
            iconCls: 'ametysicon-paintbrush',
            title: controller.getInitialConfig()['label'],
            helpMessage: "{{i18n PLUGINS_QUERIESDIRECTORY_DIALOG_APPLY_FORMATING_HINT}}",
            type: Ametys.plugins.queriesdirectory.model.QueryFormatting.FORMATTING_TYPE,
            profileAccess: 'read_access',
            value: tool.getParams().formattingQueryId,
            chooseQueryCallback: function (response) {
                me._onApplyFormatting(response)
            }
        });

    },
    
    _onApplyFormatting: function(response)
    {
        var id = response.id;
        Ametys.plugins.queriesdirectory.QueriesDAO.getQuery(id, function (q) {
            var query = Ametys.plugins.queriesdirectory.model.QueryFactory.create(q.getType(), q.getId(), q.getContent(), q.getTitle(), !q.getCanWrite());
            query.execute()
        });
    }
});