/*
 *  Copyright 2021 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 is a relation handler between:
 * * source : a form question
 * * destination : a form page
 * 
 * Or between :
 * * source : a form page
 * * destination: a form
 * 
 * @private
 */
Ext.define('Ametys.plugins.forms.relations.FormsRelationHandler', {
	extend: 'Ametys.relation.RelationHandler',
	
	/** 
	 * @protected
	 * @property {RegExp} sourceTargetId The message target type of the source to handle
	 */
	sourceTargetId: /^(form-question|form-page)$/,
	
	/**
	 * @protected
	 * @property {RegExp} destTargetId The message target type of the target to handle
	 */
	destTargetId: /^(form-page|form-target)$/,
	
	supportedRelations: function(source, target)
	{
		return this._supportedRelations(source.targets, target.targets);
	},
	
	/**
	 * @protected
	 * Do the #supportedRelations work but based only on targets array
	 * This method return the list of supported operations between the source and the target points of a relation.
	 * The implementation should only cares about targets and does not have to check upon source and target relations: a later filter is done by the Ametys.relation.RelationManager.
	 * @param {Object/Object[]/Ametys.message.MessageTarget/Ametys.message.MessageTarget[]} sourceTargets The source point of the relation operation. Targets are assumed to be ready.
	 * @param {Object/Object[]/Ametys.message.MessageTarget/Ametys.message.MessageTarget[]} targetTargets The end point of the relation operation. Targets are assumed to be ready.
	 * @return {Ametys.relation.Relation/Ametys.relation.Relation[]} Returns the supported operations between those two points. The order is important: after filtering that array, the first relation is considered as the default one.
	 */
	_supportedRelations: function(sourceTargets, targetTargets)
	{
		sourceTargets = Ext.Array.from(sourceTargets);
		targetTargets = Ext.Array.from(targetTargets);
		
		var sourceMatch = Ametys.message.MessageTargetHelper.findTargets(sourceTargets, this.sourceTargetId, 1);
		if (sourceMatch.length != 1 || sourceTargets.length != 1)
		{
			// Source should be a single question or page
			return [];
		}
		
		var targetMatch = Ametys.message.MessageTargetHelper.findTargets(targetTargets, this.destTargetId, 1);
		if (targetMatch.length != 1 || targetTargets.length != 1)
		{
			// Target should be a single page or form
			return [];
		}
		
		if (sourceMatch[0].isMessageTarget)
		{
			var sourceId = sourceMatch[0].getId();
		}
		else
		{
			var sourceId = sourceMatch[0].id;
		}
		
		if (targetMatch[0].isMessageTarget)
		{
			var targetId = targetMatch[0].getId();
		}
		else
		{
			var targetId = targetMatch[0].id;
		}
		
		var correctRelation = (sourceId == Ametys.message.MessageTarget.FORM_QUESTION && targetId == Ametys.message.MessageTarget.FORM_PAGE ||
								sourceId == Ametys.message.MessageTarget.FORM_PAGE && targetId == Ametys.message.MessageTarget.FORM_TARGET);
		if (!correctRelation)
		{
			return [];
		}
			
		var relations = [];
		relations.push(Ext.create('Ametys.relation.Relation', {
			type: Ametys.relation.Relation.MOVE,
			label: "{{i18n PLUGINS_FORMS_RELATIONS_LABEL}}",
			description: "{{i18n PLUGINS_FORMS_RELATIONS_DESCRIPTION}}",
			smallIcon: null,
			mediumIcon: null,
			largeIcon: null
		}));
			
		return relations;
	},
	
	link: function(source, target, callback, relationType)
	{
		this._link(source.getTargets(), target.getTarget(), target.positionInTargets, callback, relationType);
	},
	
	/**
	 * @protected
	 * Do the #link work but based only on targets array
	 * The method is called to link source to target using the given relation. 
	 * This operation can be asynchronous and will call callback at the end.
	 * In most cases this implementation will send a Ametys.message.Message to inform the UI that the operation was done.
	 * @param {Ametys.message.MessageTarget[]} sourceTargets The source point of the link operation. Targets are assumed to be ready.
	 * @param {Ametys.message.MessageTarget} target The end point of the link operation. Targets are assumed to be ready.
	 * @param {Number} index The insert position in child nodes. -1 means as last child.
	 * @param {Function} callback The callback to call when operation has ended. 
	 * @param {boolean} callback.sucess True if the operation was successful
	 * @param {String} relationType The relation to create. One of the constants Ametys.relation.Relation.MOVE, Ametys.relation.Relation.COPY or Ametys.relation.Relation.REFERENCE.
	 */
	_link: function(sourceTargets, target, index, callback, relationType)
	{
		var me = this;
		Ext.Array.forEach(Ametys.message.MessageTargetHelper.findTargets(sourceTargets, this.sourcetargetId, 1), function(sourceTarget) {
			
			var id = sourceTargets[0].getParameters().id;
			if (sourceTargets[0].getId() == Ametys.message.MessageTarget.FORM_PAGE)
			{
				var oldParent = sourceTargets[0].getParameters().formId;
			}
			else if (sourceTargets[0].getId() == Ametys.message.MessageTarget.FORM_QUESTION)
			{
				var oldParent = sourceTargets[0].getParameters().pageId;
			}
			var newParent = target.getParameters().id;
			
			Ametys.plugins.forms.dao.FormPageDAO.moveObject (
					[id, oldParent, newParent, index],
					me._linkCb,
					{scope: this, arguments: [callback]}
			);
		});
	},
	
	/**
	 * @private
	 * Callback of the link operation. That will call the initial callback.
	 * @param {Object} response The server response
	 * @param {Object[]} args the callback arguments
	 */
	_linkCb: function(response, args)
	{
		args[0](response.id != null);
	}
});