/*
 *  Copyright 2010 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 holds static methods about skins
 */
Ext.define('Ametys.plugins.skineditor.skin.SkinActions',
{
	singleton: true,
	
	SERVER_ROLE: "org.ametys.plugins.skineditor.skin.SkinDAO",

	// ----------------------------------- OPEN ------------------------------------

	/**
	 * Open action, to open the Skin Editor Tool.
	 */
	open: function ()
	{
		// Open the skin
		Ametys.data.ServerComm.callMethod(
		{
			role: Ametys.plugins.skineditor.skin.SkinActions.SERVER_ROLE,
			methodName: "getSkinsList",
			callback:
			{
				scope: this,
				handler: this._skinsListCb
			},
			waitMessage: true
		});
	},

	/**
	 * Callback for the getSkinsList server call
	 * @param {Object[]} skinsList The list of skins on the current site
	 * @private
	 */
	_skinsListCb: function (skinsList)
	{
        if (skinsList.length == 0)
        {
            Ametys.Msg.show(
            {
                title: "{{i18n PLUGINS_SKINEDITOR_COMMITCHANGES_LABEL}}",
                msg: "{{i18n PLUGINS_SKINEDITOR_COMMITCHANGES_OPENFILES_ERROR}}",
                buttons: Ext.Msg.OK,
                icon: Ext.MessageBox.ERROR
            });
        }
		else if (skinsList.length == 1)
		{
			this.openSkin(skinsList[0].id);
		}
		else
		{
			Ametys.plugins.skineditor.skin.ChooseSkin.open(skinsList, Ext.bind(this.openSkin, this));
		}
	},

	/**
	 * Action to open a skin based on its name
	 * @param {String} skinName The skin name
	 */
	openSkin: function (skinName)
	{
		if (skinName != null)
		{
			Ametys.plugins.skincommons.helper.SkinHelper.getSkinModel(Ametys.plugins.skineditor.skin.SkinActions.SERVER_ROLE, null, skinName, null, Ext.bind(this._getSkinModelCb, this));
		}
	},

	/**
	 * Callback for the {#Ametys.plugins.skincommons.helper.SkinHelper.getSkinModel} call
	 * @param {String} skinName The skin name
	 * @param {String} model The model of the skin. Can be null if the skin has no model
	 */
	_getSkinModelCb: function (skinName, model)
	{
		if (model != null)
		{
			Ametys.plugins.skineditor.skin.UnlinkModel.open(model, skinName, Ext.bind(this._checkLockParams, this, [skinName], true));
		}
		else
		{
			this._checkLockParams(false, skinName);
		}
	},

	/**
	 * Check the lock params for the current skin
	 * @param {Boolean} unlinkModel True to unlink the skin from its model
	 * @param {String} skinName The name of the skin
	 * @private
	 */
	_checkLockParams: function (unlinkModel, skinName)
	{
		Ametys.plugins.skincommons.helper.SkinHelper.getLockParams(Ametys.plugins.skineditor.skin.SkinActions.SERVER_ROLE, null, skinName, Ext.bind(this._getLockParamsCb, this, [unlinkModel, skinName], true));
	},

	/**
	 * Callback for the {#_checkLockParams} server call.
	 * @param {Object} lockParams The lock informations
	 * @param {Boolean} unlinkModel True to unlink the skink from its model
	 * @param {String} skinName The skin name
	 */
	_getLockParamsCb: function (lockParams, unlinkModel, skinName)
	{
		if (lockParams.isLocked || (lockParams.toolId != null && lockParams.toolId != 'uitool-skineditor'))
		{
			var msg = "";
			if (lockParams.isLocked)
			{
				// The skin is locked by another user
				msg = "{{i18n plugin.skincommons:PLUGINS_SKINCOMMONS_USER_LOCKED_CONFIRM_1}}" + "<b>" + lockParams.lockOwner + "</b>" + "{{i18n plugin.skincommons:PLUGINS_SKINCOMMONS_USER_LOCKED_CONFIRM_2}}" + lockParams.toolTitle + "{{i18n plugin.skincommons:PLUGINS_SKINCOMMONS_USER_LOCKED_CONFIRM_3}}" + lockParams.lockDate + "{{i18n plugin.skincommons:PLUGINS_SKINCOMMONS_USER_LOCKED_CONFIRM_4}}";

				if (lockParams.toolId != 'uitool-skinfactory')
				{
					// ... and by another tool
					msg += "{{i18n plugin.skincommons:PLUGINS_SKINCOMMONS_USER_LOCKED_CONFIRM_5}}";
				}
				msg += "{{i18n plugin.skincommons:PLUGINS_SKINCOMMONS_USER_LOCKED_CONFIRM_6}}";
			}
			else
			{
				// The skin is locked by the current user by another tool
				msg = "{{i18n plugin.skincommons:PLUGINS_SKINCOMMONS_TOOL_LOCKED_CONFIRM_1}}" + lockParams.toolTitle + "{{i18n plugin.skincommons:PLUGINS_SKINCOMMONS_TOOL_LOCKED_CONFIRM_2}}" + lockParams.lockDate + "{{i18n plugin.skincommons:PLUGINS_SKINCOMMONS_TOOL_LOCKED_CONFIRM_3}}";
			}

            var me = this;
			Ametys.Msg.show({
				title: "{{i18n PLUGINS_SKINEDITOR_TOOL_LABEL}}",
				msg: msg,
				buttons: Ext.MessageBox.YESNO,
				fn: function (answer)
				{
					if (answer == 'yes')
					{
						Ametys.plugins.skincommons.helper.ChooseOpenMode.open({
							iconCls: 'ametysicon-html25 decorator-ametysicon-painter14',
							title: "{{i18n PLUGINS_SKINEDITOR_TOOL_LABEL}}",
							helpMessage: "{{i18n plugin.skincommons:PLUGINS_SKINCOMMONS_CHOOSEOPENMODE_TEMP_HINT}}",
							lockDate: lockParams.lockDate,
							lastSave: lockParams.lastSave,
							callback: Ext.bind(me._chooseModeCb, me, [skinName, unlinkModel], true)
						});
					}
				},
				icon: Ext.MessageBox.WARNING
			});
		}
		else if (lockParams.lockDate || lockParams.lastSave)
		{
			// There are unsave modifications
			Ametys.plugins.skincommons.helper.ChooseOpenMode.open({
				iconCls: 'ametysicon-html25 decorator-ametysicon-painter14',
				title: "{{i18n PLUGINS_SKINEDITOR_TOOL_LABEL}}",
				helpMessage: lockParams.lockDate == null ? "{{i18n plugin.skincommons:PLUGINS_SKINCOMMONS_CHOOSEOPENMODE_WORK_HINT}}" : "{{i18n plugin.skincommons:PLUGINS_SKINCOMMONS_CHOOSEOPENMODE_TEMP_HINT}}",
				lockDate: lockParams.lockDate,
				lastSave: lockParams.lastSave,
				callback: Ext.bind(this._chooseModeCb, this, [skinName, unlinkModel], true)
			});
		}
		else
		{
			// Open tool in prod mode
			this._doOpen(skinName, 'prod', unlinkModel);
		}
	},

	/**
	 * @private
	 * Callback when the mode of edition for the skin has been choosed
	 * @param {String} mode the mode: 'temp', 'work' or 'prod'
	 * @param {String} skinName the skin name
	 * @param {Boolean} unlinkModel true to unlink the skin from its model
	 */
	_chooseModeCb: function (mode, skinName, unlinkModel)
	{
		if (mode != null)
		{
			this._doOpen(skinName, mode, unlinkModel);
		}
	},

	/**
	 * @private
	 * Launch the server call to prepare the skin for edition
	 * @param {String} skinName The skin name
	 * @param {String} mode The edition mode: 'temp', 'work' or 'prod'
	 * @param {Boolean} unlinkModel true to unlink the skin from its model before opening.
	 */
	_doOpen: function (skinName, mode, unlinkModel)
	{
		// Open the skin
		Ametys.data.ServerComm.callMethod({
			role: Ametys.plugins.skineditor.skin.SkinActions.SERVER_ROLE,
			methodName: "openSkin",
			parameters: [skinName, mode, unlinkModel],
			callback:
			{
				scope: this,
				handler: this._doOpenCb
			},
			waitMessage: true
		});
	},

	/**
	 * Callback for the {#_doOpen} method. Starts the tool if the server successfully prepared the skin repository
	 * @param {String} skinName The skin name
	 */
	_doOpenCb: function (skinName)
	{
		Ametys.tool.ToolsManager.openTool("uitool-skineditor", { "skinName" : skinName });
	},


	// ----------------------------------- REVERT ------------------------------------
	/**
	 * Action to revert any changes made to the skin
	 */
	revertChanges: function ()
	{
		var tool = Ametys.tool.ToolsManager.getTool('uitool-skineditor');
		var skinName = tool.getSkinName();

		Ametys.plugins.skincommons.CommonSkinActions.cancelChanges(Ametys.plugins.skineditor.skin.SkinActions.SERVER_ROLE, skinName, false, 'uitool-skineditor', Ext.bind(this._revertChangesCb, this));
	},

	/**
	 * Callback after the changes were reverted. Refresh the impacted tools
	 * @param {Boolean} success True if the changes were reverted
	 */
	_revertChangesCb: function (success)
	{
		if (success)
		{
			// Refresh tool
			var tool = Ametys.tool.ToolsManager.getTool('uitool-skineditor');
			tool.refresh();

			// Refresh editors
			var tools = Ametys.tool.ToolsManager.getTools();
			for (var i in tools)
			{
				if (i.indexOf('uitool-skin-file-editor$') == 0)
				{
					tools[i].refresh(true);
				}
			}
		}
	},

	
	// ----------------------------------- PREVIEW ------------------------------------
	
	/**
	 * Action to preview the current modified skin
	 */
	preview: function ()
	{
		var lang = Ametys.cms.language.LanguageDAO.getCurrentLanguage();

		Ametys.data.ServerComm.callMethod(
		{
			role: Ametys.plugins.skineditor.skin.SkinActions.SERVER_ROLE,
			methodName: "getPreviewURI",
			parameters: [Ametys.getAppParameter("siteName"), lang],
			callback:
			{
				handler: function (uri)
				{
					var previewUrl = Ametys.getPluginDirectPrefix('skincommons') + '/preview/' + Ametys.getAppParameter("siteName") + '/' + uri;
					Ametys.openWindow (previewUrl, null, 'GET');
				}
			}
		});
	},

	
	// ----------------------------------- SAVE ------------------------------------

	/**
	 * Action to change the current modification of the skin
	 */
	saveChanges: function ()
	{
		this._doSave(false);
	},

	/**
	 * Action to change the current modification of the skin, and close the editor
	 */
	saveChangesAndQuit: function ()
	{
		this._doSave(true);
	},

	/**
	 * Save the changes of the skin
	 * @param {Boolean} quit True to close the editor after saving
	 * @private
	 */
	_doSave: function (quit)
	{
		var tool = Ametys.tool.ToolsManager.getTool('uitool-skineditor');
		var skinName = tool.getSkinName();

		Ametys.plugins.skincommons.CommonSkinActions.saveChanges(Ametys.plugins.skineditor.skin.SkinActions.SERVER_ROLE, skinName, quit, Ext.bind(this._saveChangesCb, this));
	},

	/**
	 * Callback for the {#_doSave} method.
	 * @param {Boolean} success True if the changes were successfully saved
	 * @param {Boolean} quit True to close the tools after saving
	 */
	_saveChangesCb: function (success, quit)
	{
		if (success && quit)
		{
			// Close tool
			Ametys.tool.ToolsManager.getTool('uitool-skineditor').close();

			// Close editors
			var tools = Ametys.tool.ToolsManager.getTools();
			for (var i in tools)
			{
				if (i.indexOf('uitool-mixed-editor$') === 0 || i.indexOf('uitool-css-editor$') === 0 || i.indexOf('uitool-js-editor$') === 0)
				{
					tools[i].close();
				}
			}
		}
	},

	
	// ----------------------------------- COMMIT ------------------------------------
	
	/**
	 * Action to commit the current modification to the skin
	 */
	commitChanges: function ()
	{
		this._startCommit(false);
	},

	/**
	 * Action to commit the current modification to the skin, and close the tools after.
	 */
	commitChangesAndQuit: function ()
	{
		this._startCommit(true);
	},

	/**
	 * Commit the changes into the real skin
	 * @param {Boolean} quit True to close the skin after edition
	 * @private
	 */
	_startCommit: function (quit)
	{
		// Check the open tools
		if (!this._checkOpenFiles())
		{
			Ametys.Msg.show(
			{
				title: "{{i18n PLUGINS_SKINEDITOR_COMMITCHANGES_LABEL}}",
				msg: "{{i18n PLUGINS_SKINEDITOR_COMMITCHANGES_OPENFILES_ERROR}}",
				buttons: Ext.Msg.OK,
				icon: Ext.MessageBox.ERROR
			});
			return;
		}

		Ametys.Msg.confirm("{{i18n PLUGINS_SKINEDITOR_COMMITCHANGES_LABEL}}",
			"{{i18n PLUGINS_SKINEDITOR_COMMITCHANGES_CONFIRM}}",
			function (btn)
			{
				if (btn == 'yes')
				{
					this._doCommit(quit);
				}
			},
			this
		);
	},

	/**
	 * Verify if any tool is currently in edition
	 * @return {Boolean} True if all the tools are clean
	 * @private
	 */
	_checkOpenFiles: function ()
	{
		var tools = Ametys.tool.ToolsManager.getTools();
		for (var i in tools)
		{
			if (i.indexOf('uitool-mixed-editor$') === 0 || i.indexOf('uitool-css-editor$') === 0 || i.indexOf('uitool-js-editor$') === 0)
			{
				if (tools[i].isDirty())
				{
					return false;
				}
			}
		}
		return true;
	},

	/**
	 * Callback for the confirmation button. Do the commit
	 * @param {Boolean} quit True to close the tools after commiting
	 */
	_doCommit: function (quit)
	{
		var tool = Ametys.tool.ToolsManager.getTool("uitool-skineditor");

		Ametys.plugins.skincommons.CommonSkinActions.commitChanges(Ametys.plugins.skineditor.skin.SkinActions.SERVER_ROLE, tool.getSkinName(), quit, Ext.bind(this._commitCb, this));
	},

	/**
	 * Callback for the {#_doCommit} method.
	 * @param {Boolean} success True if the commit was successful
	 * @param {Boolean} quit True to close all the skin editor tools
	 */
	_commitCb: function (success, quit)
	{
		if (this._waitMsg != null)
		{
			this._waitMsg.hide();
			delete this._waitMsg;
		}

		if (success && quit)
		{
			// Close tool
			Ametys.tool.ToolsManager.getTool('uitool-skineditor').close();

			// Close editors
			var tools = Ametys.tool.ToolsManager.getTools();
			for (var i in tools)
			{
				if (i.indexOf('uitool-mixed-editor$') === 0 || i.indexOf('uitool-css-editor$') === 0 || i.indexOf('uitool-js-editor$') === 0)
				{
					tools[i].close();
				}
			}
		}
	}

});