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

/**
 * This class is the representation of a page.
 */
Ext.define(
	"Ametys.web.page.Page", 
	{
		config: {
			/**
			 * @cfg {String} id The unique id of the page
			 */
			/**
			 * @method getId Get the #cfg-id
			 * @return {String} The id
			 */
			/** @ignore */
			id: null,
			/**
			 * @cfg {String} parentId The id of the parent page
			 */
			/**
			 * @method getParentId Get the #cfg-parentId
			 * @return {String} The parent id
			 */
			/** @ignore */
			parentId: null,
			/**
			 * @cfg {String} title The title of the page
			 */
			/**
			 * @method getTitle Get the #cfg-title
			 * @return {String} The title
			 */
			/** @ignore */
			title: null,
			/**
			 * @cfg {String} path The path in the sitemap of the page
			 */
			/**
			 * @method getPath Get the #cfg-path
			 * @return {String} The path
			 */
			/** @ignore */
			path: null,
			/**
			 * @cfg {String} type The type of the page
			 */
			/**
			 * @method getType Get the #cfg-type
			 * @return {String} The type
			 */
			/** @ignore */
			type: null,
			/**
			 * @cfg {String} lang The lang of the page
			 */
			/**
			 * @method getLang Get the #cfg-lang
			 * @return {String} The lang
			 */
			/** @ignore */
			lang: null,
			
			/**
			 * @cfg {String} siteName The site name
			 */
			/**
			 * @method getSiteName Get the #cfg-siteName
			 * @return {String} The site name
			 */
			/** @ignore */
			siteName: null,
            /**
             * @cfg {boolean} isModifiable True if this page can be modified. False if it read-only: this is not about rights. Can be false for a virtual page... but basically not stored in JCR
             */
            /**
             * @method getIsModifiable Get the #cfg-isModifiable
             * @return {boolean} The page is modifiable
             */
            /** @ignore */
            isModifiable: false,
            /**
             * @cfg {boolean} isTaggable True if this page can be tagged.
             */
            /**
             * @method getIsTaggable Get the #cfg-isTaggable
             * @return {boolean} The page is taggable
             */
            /** @ignore */
            isTaggable: false,
			/**
			 * @cfg {boolean} isMoveable True if this page can be moved. This is not about rights. Can be false for a virtual page... but basically not stored in JCR
			 */
			/**
			 * @method getIsMoveable Get the #cfg-isMoveable
			 * @return {boolean} The page is moveable
			 */
			/** @ignore */
			isMoveable: false,
            /**
             * @cfg {boolean} isVisible True if this page is visible
             */
            /**
             * @method getIsVisible Get the #cfg-isVisible
             * @return {boolean} The page is visible
             */
            /** @ignore */
            isVisible: false,
            /**
             * @cfg {boolean} isParentInvisible True if this page has a parent that is invisible
             */
            /**
             * @method getIsParentInvisible Get the #cfg-isParentInvisible
             * @return {boolean} The page has a parent that is invisible
             */
            /** @ignore */
            isParentInvisible: false,
			/**
			 * @cfg {String[]} rights List of the id of the rights the current user have on this page
			 */
			/**
			 * @method getRights Get the #cfg-rights
			 * @return {String[]} The rights
			 */
			/** @ignore */
			rights: [],
			
			/**
			 * @cfg {Object[]} zones List of the zones of on this page
			 */
			/**
			 * @method getZones Get the #cfg-zones
			 * @return {Object[]} The zones
			 */
			/** @ignore */
			zones: [],
			
			/**
			 * @cfg {String[]} contents The identifiers of contents containing in this page
			 */
			/**
			 * @method getContents Get the #cfg-contents
			 * @return {Object[]} The id of contents
			 */
			/** @ignore */
			contents: [],
			
			/**
			 * @cfg {String} url The redirection url if the page is a 'link' page.
			 */
			/**
			 * @method getUrl Get the #cfg-url
			 * @return {String} The redirection url
			 */
			/** @ignore */
			url: null,
			
			/**
			 * @cfg {String} urlType The type of redirection if the page is a 'link' page.
			 */
			/**
			 * @method getUrlType Get the #cfg-urlType
			 * @return {String} The type of redirection
			 */
			/** @ignore */
			urlType: null,
            
            /**
             * @cfg {String} urlTitle The title of redirection url or page, if the page is a 'link' page.
             */
            /**
             * @method getUrlTitle Get the #cfg-urlTitle
             * @return {String} The type of redirection
             */
            /** @ignore */
            urlTitle: null,
            
            /**
             * @cfg {Object} publication The publication dates of the page.
             * @cfg {Date} publication.startDate The publication start date.
             * @cfg {Date} endDate The publication start date.
             */
            /**
             * @method getPublication Get the #cfg-publication
             * @return {Object} The publication dates
             */
            /** @ignore */
            publication: null,
			
			/**
			 * @cfg {String} template The template of the page. This is not null if the page is a 'container' page.
			 */
			/**
			 * @method getTemplate Get the #cfg-template
			 * @return {String} The page template
			 */
			/** @ignore */
			template: null,
			
			/**
			 * @cfg {String} [messagetTarget=Ametys.message.MessageTarget#PAGE] The message target type
			 */
			messageTarget: null,
            
            /**
             * @cfg {boolean} isPreviewable True if this page is previewable
             */
            /**
             * @method getIsPreviewable Get the #cfg-isPreviewable
             * @return {boolean} The page is previewable
             */
            /** @ignore */
            isPreviewable: false,
            
            /**
             * @cfg {boolean} isPageValid True if this page is valid
             */
            /**
             * @method getIsPageValid Get the #cfg-isPageValid
             * @return {boolean} The page is valid
             */
            /** @ignore */
            isPageValid: false,
            
            /**
             * @cfg {boolean} isLiveHierarchyValid True if this page has it's hierarchy valid (in live)
             */
            /**
             * @method getIsLiveHierarchyValid Get the #cfg-isLiveHierarchyValid
             * @return {boolean} The page has it's hierarchy valid (in live)
             */
            /** @ignore */
            isLiveHierarchyValid: false,
			
			/**
			 * @method getLocked Get the #cfg-locked
			 * @return {Boolean} The locked state
			 */
			/** @ignore */
			locked: false,
		},
		
		statics: {
			/**
			 * @property {String} URL_TYPE_PAGE Type of redirection towards CMS page
			 */
			URL_TYPE_PAGE: 'PAGE',
			
			/**
			 * @property {String} URL_TYPE_PAGE Type of redirection towards external web page
			 */
			URL_TYPE_EXTERNAL: 'WEB',
		},
		
		/**
		 * Creates a page instance
		 * @param {Object} config See configuration doc.
		 */
		constructor: function (config)
		{
			this.initConfig(config);
			
			this._messageTarget = config.messageTarget || Ametys.message.MessageTarget.PAGE;
		},
		
		/**
		 * Determines if the current user has the specified right on the page
		 * @param {String} rightId The identifier of the right to check
		 * @return {boolean} True or false
		 */
		hasRight: function(rightId)
		{
			return Ext.Array.contains(this._rights, rightId);
		},
		
		/**
		 * Get the page's properties
		 * @return {Object} The page's properties
		 */
		getProperties: function (initialProperty)
		{
			return Ext.apply ({
					id: this._id,
					parentId: this._parentId,
					title: this._title,
					path: this._path,
					type: this._type,
					url: this._url,
					urlType: this._urlType,
					lang: this._lang,
					locked: this._locked,
					siteName: this._siteName,
					isModifiable : this._isModifiable,
					isMoveable : this._isMoveable,
					template: this._template,
					rights: this._rights
				}, initialProperty
			);
		},
		
		/**
		 * Try to lock the page.
		 * If the page was already locked, the callback is called with 'true' as argument
		 * @param {Function} callback The method to call
		 * @param {boolean} callback.success true if the lock was a success, else false (and a message was already displayed to the user)
		 */
		lock: function(callback)
		{
			if (!this._locked)
			{    
				// Try to lock the content
				Ametys.data.ServerComm.callMethod({
					role: "org.ametys.web.repository.page.PageDAO",
					methodName: "unlockOrLock",
					parameters: [this._id, 'lock'],
					callback: {
						scope: this,
						handler: this._unlockOrLockCb,
						arguments: {callback: callback}
					},
					errorMessage: {
						msg: "{{i18n PLUGINS_WEB_PAGE_LOCK_ERROR}}",
						category: 'Ametys.web.page.Page'
					}
				});
			}
			else if (Ext.isFunction(callback))
			{
				callback(true);
			}
		},
		
		/**
		 * Try to unlock the page.
		 * If the page was already locked, the callback is called with 'true' as argument
		 * @param {Function} callback The method to call
		 * @param {boolean} callback.success true if the lock was a success, else false (and a message was already displayed to the user)
		 */
		unlock: function(callback)
		{
			if (this._locked)
			{
				// Try to unlock the content
				Ametys.data.ServerComm.callMethod({
					role: "org.ametys.web.repository.page.PageDAO",
					methodName: "unlockOrLock",
					parameters: [this._id, 'unlock'],
					callback: {
						scope: this,
						handler: this._unlockOrLockCb,
						arguments: {callback: callback}
					},
					errorMessage: {
						msg: "{{i18n PLUGINS_WEB_PAGE_LOCK_ERROR}}",
						category: 'Ametys.web.page.Page'
					}
				});
			}
			else if (Ext.isFunction(callback))
			{	
			     callback(true);
			}
		},
		
		/**
		 * Callback function called after #unlockOrLock is processed.
		 * Fires Ametys.message.Message#LOCK_CHANGED message for locked or unlocked page
		 * @param {Object[]} response the server response
		 * @param {String} response.mode the mode ( unlock or lock )
		 * @param {String} response.pageId the id of the unlocked or locked page
		 * @param {String} response.pageTitle the unlocked or locked page title
		 * @param {String} response.error the reason the locking or unlocking failed 
		 * @param {Object[]} args the callback arguments
		 * @param {String} args.page the message target id
		 * @private
	 	*/
		_unlockOrLockCb: function (response, args)
		{
			var callback = args['callback'];
			var pageTitle = response.pageTitle
			var success = false;
			if (response.error)
			{
				var msg = "";
				switch (response.error)
				{
					case "still-locked-page":
						msg = Ext.String.format("{{i18n PLUGINS_WEB_PAGE_UNLOCK_ACTION_STILL_LOCKED}}", pageTitle);
						break;
					case "fail-locked-page":
						msg = Ext.String.format("{{i18n PLUGINS_WEB_PAGE_UNLOCK_ACTION_FAILED}}", pageTitle);
						break;
					case "already-locked-page":
						msg = Ext.String.format("{{i18n PLUGINS_WEB_PAGE_LOCK_ACTION_ALREADY_LOCKED}}", pageTitle);
						break;
					case "fail-unlocked-page":
						msg = Ext.String.format("{{i18n PLUGINS_WEB_PAGE_LOCK_ACTION_FAILED}}", pageTitle);
						break;
					default:
						msg = "";
				}
				
				Ametys.log.ErrorDialog.display({
					title: "{{i18n PLUGINS_WEB_PAGE_LOCK_ACTION_ERROR}}",
					text: msg,
					details: "",
					category: "Ametys.plugins.cms.content.controller.LockController.act"
				});
			}
			else
			{
				success = true;
				Ext.create("Ametys.message.Message", {
					type: Ametys.message.Message.LOCK_CHANGED,
					
					targets: [{
						id: Ametys.message.MessageTarget.PAGE,
						parameters: { ids: [response.pageId] }
					}]
				});
			}
			
			if (Ext.isFunction(callback))
			{
				callback(success);
			}
		},
		
		/**
		 * Get the identifiers of contents of this page
		 * @return {String[]} The contents' id.
		 */
		getContentIds: function ()
		{
			var contentIds = [];
			Ext.Array.forEach (this._zones, function (zone) {
				var zoneitems = zone.zoneitems || [];
				
				Ext.Array.forEach (zoneitems, function (zoneitem) {
					
					if (zoneitem.content)
					{
						contentIds.push(zoneitem.content.id)
					}
    				
    			});
			});
			return contentIds;
		}
	}
);