/*
 *  Copyright 2023 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 : tag
 * * destination : tag or tag provider
 * 
 * E.g. when you drag a tag to another tag
 * @private
 */
Ext.define('Ametys.repository.relations.DefaultNodeRelationHandler', {
    extend: 'Ametys.relation.RelationHandler',
    
    /**
     * @protected
     * @template
     * Get the regexp to match target
     */
    _getRegexp: function()
    {
        return /^repository-node$/;
    },
    
    /**
     * @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 {Ametys.message.MessageTarget[]} sourceTargets The source point of the relation operation. Targets are assumed to be ready.
     * @param {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)
    {
        var sourceMatch = Ametys.message.MessageTargetHelper.findTargets(sourceTargets, this._getRegexp(), 1);
        if (sourceMatch.length == 0 || sourceMatch.length != sourceTargets.length)
        {
            return [];
        }
        
        var targetMatch = Ametys.message.MessageTargetHelper.findTargets(targetTargets, this._getRegexp(), 1);
        if (targetMatch.length != 1 || targetTargets.length != 1)
        {
            return [];
        }
        
        for (s of sourceMatch)
        {
            if (s.parameters && s.parameters.workspaceName != targetMatch[0].parameters.workspaceName
                || s.getParameters && s.getParameters().workspaceName != targetMatch[0].getParameters().workspaceName)
            {
                return [];
            }
        }

        var relations = [ 
            Ext.create('Ametys.relation.Relation', {
                type: Ametys.relation.Relation.MOVE,
                label: "{{i18n PLUGINS_REPOSITORY_RELATION_DEFAULT_MOVE_LABEL}}",
                description: "{{i18n PLUGINS_REPOSITORY_RELATION_DEFAULT_MOVE_DESCRIPTION}}",
                smallIcon: null,
                mediumIcon: null,
                largeIcon: null
            })
        ];
        
        return relations;
    },
    
    supportedRelations: function(source, target)
    {
        return this._supportedRelations(source.targets, target.targets);
    },
    
    /**
     * @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.success True if the operation was successful
     */
    _link: function(sourceTargets, target, index, callback)
    {
        var me = this;

        var sourceIds = [];
        Ext.Array.forEach(Ametys.message.MessageTargetHelper.findTargets(sourceTargets, this._getRegexp(), 1), function(target) {
            sourceIds.push(target.getParameters().pathWithGroups);
        });

        var workspaceName = Ametys.repository.RepositoryApp.getCurrentWorkspace();
        
        Ext.create('Ametys.message.Message', {
            type: Ametys.message.Message.DELETING,
            
            targets: {
                id: Ametys.message.MessageTarget.REPOSITORY_NODE,
                parameters: {
                    paths: sourceIds,
                    workspaceName: workspaceName
                }
            },
            callback: function(deletingMsg) {
                    Ametys.data.ServerComm.callMethod({
                        role: 'org.ametys.workspaces.repository.jcr.RepositoryDao', 
                        methodName: 'moveNodes',
                        parameters: [sourceIds, workspaceName, target.getParameters().pathWithGroups, index],
                        callback: {
                            handler: me._linkCb,
                            scope: me,
                            arguments: {
                                callback: callback,
                                workspaceName: workspaceName,
                                targets: deletingMsg.getTargets()
                            }
                        },
                        errorMessage: "{{i18n PLUGINS_REPOSITORY_RELATION_DEFAULT_MOVE_ERROR}}"
                    });
            }
        });
    },
    
    link: function(source, target, callback, relationType)
    {
        this._link(source.getTargets(), target.getTarget(), target.positionInTargets, callback);
    },
    
    /**
     * @private
     * Callback of the link operation. That will call the initial callback.
     */
    _linkCb: function(result, args)
    {
        // Send the deleted message with stored targets
        Ext.create('Ametys.message.Message', {
            type: Ametys.message.Message.DELETED,
            targets: args.targets
        });
                
        Ext.create("Ametys.message.Message", {
            type: Ametys.message.Message.MOVED,
            targets: {
                id: Ametys.message.MessageTarget.REPOSITORY_NODE,
                parameters: {
                    paths: result.path,
                    workspaceName: args.workspaceName
                }
            },
            parameters: {
                major: true
            }
        });
        
        args.callback(true);
    }
});