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

/**
 * Singleton class defining the actions related to the plugins and workpaces tools
 * @private
 */
Ext.define('Ametys.plugins.web.sitemap.SitemapActions', {
	singleton: true,
	
	/**
	 * @private
	 * @property {Ametys.window.DialogBox} _box The dialog box for creating a new site
	 */
	
	/**
	 * Opens create page wizard to create and configure a new page.
	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 */
	createPage: function(controller)
	{
		var target = controller.getMatchingTargets()[0];
		if (target != null)
		{
			Ametys.plugins.web.page.AddPageWizard.open (target.getParameters().id, null, controller.getInitialConfig());
		}
	},
	
	/**
	 * @private
	 * Callback function called after page was created
	 * @param {String} pageId The id of created page
	 */
	_createCb: function (pageId)
	{
		Ext.create('Ametys.message.Message', {
			type: Ametys.message.Message.CREATED,
			targets: [{
				id: Ametys.message.MessageTarget.PAGE,
				parameters: {
					ids: [id]
				}
			}]
		});
		
		Ametys.tool.ToolsManager.openTool('uitool-page', {id: id});
	},
	
	/**
	 * Delete a page
	 * @param {Ametys.ribbon.element.ui.ButtonController/Ametys.message.MessageTarget} controller The controller calling this function, or directly the target
     * @param {Function} callback Callback when page is removed
     * @param {Object} texts a map of texts to use instead of the default values
     * @param {String} texts.confirm_title the title of the confirmation box to delete a page
     * @param {String} texts.confirm_text the content of the confirmation box to delete a page. Can contain {0} for the name of the page
     * @param {String} texts.confirm_orphan_title title of the dialog box to delete orphan contents
     * @param {String} texts.confirm_orphan_text content of the dialog box to delete orphan contents, can contain {0} for the name of the contents
	 */
	remove: function(controller, callback, texts)
	{
        if (controller != null && controller.isButtonController)
        {
            var target = controller.getMatchingTargets()[0];
        }
        else
        {
            target = controller;
        }
		if (target != null)
		{
            var title = "{{i18n PLUGINS_WEB_ADMINISTRATOR_SITES_DELETE_LABEL}}";
            var message = "{{i18n PLUGINS_WEB_CREATEPAGE_DELETE_CONFIRM_1}}" + '<b>' + Ext.String.escapeHtml(target.getParameters().title) + '</b>' + "{{i18n PLUGINS_WEB_CREATEPAGE_DELETE_CONFIRM_2}}";
            
            if (texts)
            {
                if (texts.confirm_title)
                {
                    title = texts.confirm_title;
                }
                if (texts.confirm_text)
                {
                    message = texts.confirm_text;
                    message = message.replace("{0}", target.getParameters().title);
                }
            }
            
            Ametys.Msg.confirm(title,
                    message,
                    Ext.bind(this._confirmDelete, this, [target.getParameters().id, target, callback, texts], 1),
                    this
            );
		}
	},
	
	/**
	 * @private
	 * The callback function invoked after the confirm box for delete process is closed
	 * @param {String} answer The ID of the button pressed
	 * @param {String} id the page id
	 * @param {Ametys.message.MessageTarget} target the page target
     * @param {Function} callback A callback function to call at the end
     * @param {Object} texts a map of texts to use instead of the default values
     * @param {String} texts.confirm_orphan_title title of the dialog box to delete orphan contents
     * @param {String} texts.confirm_orphan_text content of the dialog box to delete orphan contents, can contain {0} for the name of the contents
	 */
	_confirmDelete: function (answer, id, target, callback, texts)
	{
		if (answer == 'yes')
		{
			Ametys.web.page.PageDAO.getDeleteablePageContents ([id], this._getDeleteablePageContentsCb, {'arguments': {id: id, target: target, callback: callback, texts: texts}, scope: this});
		}
	},
	
	/**
	 * @private
	 * Callback invoked after retrieving the unreferenced contents of the page to delete
	 * @param {Object[]} contents the unreferenced contents
	 * @param {Object} args the callback arguments
	 * @param {String} args.id the page id
	 * @param {Ametys.message.MessageTarget} args.target the page target
     * @param {Object} args.texts a map of texts to use instead of the default values
     * @param {String} args.texts.confirm_orphan_title title of the dialog box to delete orphan contents
     * @param {String} args.texts.confirm_orphan_text content of the dialog box to delete orphan contents, can contain {0} for the name of the contents
	 */
	_getDeleteablePageContentsCb: function (contents, args)
	{
		if (contents != null)
		{
			var deleteableContents = contents['deleteable-contents'];
			var lockedContents = contents['locked-contents'];
			var unauthorizedContents = contents['unauthorized-contents'];
			
			var unreferencedContentIds = [];
			var unreferencedContentTitles = [];
			Ext.Array.each (deleteableContents, function (content) {
				
				if (!content.isNew)
				{
					unreferencedContentIds.push(content.id);
					unreferencedContentTitles.push('<b>' + Ext.String.escapeHtml(content.title) + '</b>');
				}
			});
			
			if (unreferencedContentTitles.length > 0)
			{
				// There is deleteable contents that belong only to the page, ask for user confirmation to delete them.
				var me = this;
                var title = "{{i18n PLUGINS_WEB_CREATEPAGE_DELETE_REMOVE_ORPHAN_CONTENT_LABEL}}";
                var message = "{{i18n PLUGINS_WEB_CREATEPAGE_DELETE_REMOVE_ORPHAN_CONTENT_CONFIRM_1}}" + unreferencedContentTitles.join(", ") + "{{i18n PLUGINS_WEB_CREATEPAGE_DELETE_REMOVE_ORPHAN_CONTENT_CONFIRM_2}}";
                
                if (args.texts)
                {
                    if (args.texts.confirm_orphan_title)
                    {
                        title = args.texts.confirm_orphan_title;
                    }
                    if (args.texts.confirm_orphan_text)
                    {
                        message = args.texts.confirm_orphan_text;
                        message = message.replace("{0}", unreferencedContentTitles.join(", "));
                    }
                }
                
                Ametys.Msg.show({
                    title: title, 
                    message: message,
                    icon: Ext.Msg.QUESTION,
                    buttons: Ext.Msg.YESNOCANCEL,
                    fn: function (answer) {
                        if (answer == 'yes')
                        {
                            // Delete page and unreferenced contents
                            var me = this;
                            function prep(contentTargets)
                            {
                                Ametys.web.page.PageDAO.deletePage([args.id, true, args.target, contentTargets], args.callback, {});
                            }

                            // Prepare content target
                            Ametys.message.MessageTargetFactory.createTargets({
                                id: Ametys.message.MessageTarget.CONTENT,
                                parameters: {
                                    ids: unreferencedContentIds
                                }
                            }, prep);
                        }
                        else if (answer == 'no')
                        {
                            // Delete page but keep contents, except newly created contents
                            Ametys.web.page.PageDAO.deletePage([args.id, false, args.target, []], args.callback, {});
                        }
                        // else cancel => nothing
                    },
                    scope: me
	            });
			}
			else
			{
				// Delete page and unreferenced contents silently without confirmation (all deleteable contents are newly created contents)
				Ametys.web.page.PageDAO.deletePage([args.id, true, args.target, []], args.callback, {});
			}
		}
	},
	
	/**
	 * Rename a page
     * @param {Ametys.ribbon.element.ui.ButtonController/String} controller The controller calling this function, or id of the page to rename
     * @param {Object} conf Special graphic configuration for rename form (ex : {update-path:{hidden:true}})
     * @param {boolean} [conf.long-title=true] show the long-title text box
     * @param {boolean} [conf.update-path=true] show the update-path text box
     * @param {boolean} [conf.alias=true] show the alias text box
     * @param {Function} callback Callback when the rename is successfull
	 */
	renamePage: function (controller, conf, callback)
	{
        var pageId = controller;
        //handle 2 cases : when the function is called from a ButtonController, or when it is called from code
        if (controller != null && controller.isButtonController)
        {
            var target = controller.getMatchingTargets()[0];
            if (target != null)
            {
                pageId = target.getParameters().id;
            }
        }

        this._renamePage (pageId, conf, callback);
	},
    /**
     * @private
     * Rename a page
     * @param {String} pageId page Id
     * @param {Object} conf Special graphic configuration for rename form (ex : {update-path:{hidden:true}})
     * @param {Function} callback Callback when the rename is successfull
     */
    _renamePage: function (pageId, conf, callback)
    {
        if (pageId != null)
        {
            this._renameDialogDelayedInitialize();

            var defaultConf = {
                'long-title' : true,
                'update-path' : true,
                'alias' : true
            };
            conf = Ext.applyIf(conf || {}, defaultConf);

            var form = this._renameDialogBox.items.get(0).getForm();
            form.findField('long-title').setVisible(conf['long-title']);
            form.findField('update-path').setVisible(conf['update-path']);
            form.findField('alias').setVisible(conf['alias']);

            if (Ext.isFunction(callback))
            {
                this._renameCallback = callback;
            }

            this._initRenameForm (pageId);
        }
    },
	
	/**
	 * @private
	 * Get page's properties to initialize the rename dialog box
	 * @param {String} id The page id
	 */
	_initRenameForm: function (id)
	{
		Ametys.data.ServerComm.callMethod({
			role: "org.ametys.web.repository.page.PageDAO",
			methodName: "getPageInfos",
			parameters: [id],
			callback: {
				scope: this,
				handler: this._initRenameFormCb
			},
			errorMessage: true
		});
	},
	
	/**
	 * @private
	 * Initialize the rename dialog box after retrieving page properties from server
	 * @param {Object} data The page's properties
	 */
	_initRenameFormCb: function (data)
	{
		var form = this._renameDialogBox.items.get(0).getForm();
		form.findField('title').setValue(data.title);
		form.findField('long-title').setValue(data.longTitle != data.title ? data.longTitle : '');
		form.findField('id').setValue(data.id);
		
		form.findField('update-path').setValue(false);
		form.findField('alias').setValue(false);
		form.findField('alias').disable();
		
		this._renameDialogBox.show();
	},
	
	/**
	 * @private
	 * Initialize the dialog box
	 */
	_renameDialogDelayedInitialize: function ()
	{
		if (this._renameDialogInitialized)
		{
			return true;
		}
		
		var form = Ext.create('Ext.form.Panel', {
			border: false,
			scrollable: true,
			
			defaults : {
				cls: 'ametys',
				labelAlign: 'top',
				width: 450,
				msgTarget: 'side',
				xtype: 'textfield'
			},
			
			items : [{
						 xtype: 'textfield',
						 fieldLabel : "{{i18n PLUGINS_WEB_RENAMEPAGE_TITLE}}",
			        	 name: 'title',
			        	 itemId: 'title',
			        	 allowBlank: false
					 },
					 {
						 xtype: 'textfield',
						 fieldLabel : "{{i18n PLUGINS_WEB_RENAMEPAGE_TITLELONG}}",
			        	 name: 'long-title',
			        	 allowBlank: true
					 },
					 {
						 xtype: 'checkbox',
						 boxLabel : "{{i18n PLUGINS_WEB_RENAMEPAGE_CHANGEPATH}}",
						 name: 'update-path',
						 hideLabel: true,
						 //height: 60,
						 listeners: {'change': Ext.bind(this._onSelectUpdatePath, this)}
				     },
				     {
						 xtype: 'checkbox',
						 boxLabel : "{{i18n PLUGINS_WEB_RENAMEPAGE_CREATEALIAS}}",
						 name: 'alias',
						 hideLabel: true,
						 disabled: true
						 //height: 80
				     },
					 {
						xtype: 'hidden',
						name: 'id'
					 }
			]
		});
		
		this._renameDialogBox = Ext.create('Ametys.window.DialogBox', {
			title :"{{i18n PLUGINS_WEB_RENAMEPAGE_CAPTION}}",
			icon: Ametys.getPluginResourcesPrefix('web') + '/img/actions/page_rename_16.png',
			
			width: 530,
			
			items: [form],
			
			selectDefaultFocus: true,
			defaultFocus: 'title',
			
			referenceHolder: true,
			defaultButton: 'validate',

			closeAction: 'hide',
			
			buttons: [{
				reference: 'validate',
				text :"{{i18n PLUGINS_WEB_RENAMEPAGE_BTN_OK}}",
				handler : Ext.bind(this._renameOk, this)
			}, {
				text :"{{i18n PLUGINS_WEB_RENAMEPAGE_BTN_CANCEL}}",
				handler : function () {this._renameDialogBox.hide();},
				scope: this
			}]
		});
		
		this._renameDialogInitialized = true;
		
		return true;
	},
	
	/**
	 * @private
	 * Function called when validating rename dialog box
	 */
	_renameOk: function ()
	{
		var form = this._renameDialogBox.items.get(0).getForm();
		if (!form.isValid())
		{
			return;
		}
		
		var id = form.findField('id').getValue();
		var title = form.findField('title').getValue();
		var longtitle = form.findField('long-title').getValue();
		var updatePath = form.findField('update-path').getValue();
		var alias = form.findField('alias').getValue();
		
		Ametys.web.page.PageDAO.renamePage (
			[id, title, longtitle, updatePath, alias],
			this._renameCb,
			{scope: this}
		);
	},
	
	/**
	 * @private
	 * Callback function called after page was renamed
	 * @param {Object} response The server result
	 * @param {Object} args The callback arguments
	 */
	_renameCb: function (response, args)
	{
		if (!response['invalid-name'])
		{
			this._renameDialogBox.hide();
            if (Ext.isFunction(this._renameCallback))
            {
                this._renameCallback();
                this._renameCallback = null;
            }
		}
	},
	
	/**
	 * @private
	 * Listener when checking/unchecking "update path" checkbox
	 * @param {Ext.form.field.Checkbox} fd the checkbox field
	 * @param {Boolean} newValue the checkbox value
	 */
	_onSelectUpdatePath: function (fd, newValue)
	{
		var form = this._renameDialogBox.items.get(0).getForm();
		form.findField("alias").setDisabled(!newValue);
	},
	
	/**
	 * Action function to be called by the controller.
	 * Will lock or unlock the selected page according the pressed state.
	 * {Ametys.ribbon.element.ui.ButtonController/Ametys.message.MessageTarget} controller The controller calling this function, or directly the target
	 * {boolean} toLock true to lock the page (only used when function is called without using the button)
	 */
	lockPage: function(controller, toLock)
	{
		var lock = toLock ? 'lock' : 'unlock';
		if (controller != null && controller.isButtonController)
        {
            var target = controller.getMatchingTargets()[0];
			lock = controller.isPressed() ? 'unlock' : 'lock';
        }
        else
        {
            target = controller;
        }
		
		if (target != null)
        {
            var pageId = target.getParameters().id;
			if (lock == "unlock")
			{
				Ametys.web.page.PageDAO.unlockPage (
					pageId,
					target,
					this._unlockOrLockCb,
					{scope: this}
				);
			}
			else
			{
				Ametys.web.page.PageDAO.lockPage (
					pageId,
					target,
					this._unlockOrLockCb,
					{scope: this}
				);
			}
        }
	}
});