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

/**
 * @private
 * This is a relation handler between:
 * * source : file or file container
 * * destination : file container
 */
Ext.define('Ametys.plugins.extraction.ExtractionDefinitionFileRelationHandler', {
    extend: 'Ametys.relation.RelationHandler',
    
    /**
     * @private
     * 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 handle targets and should not have to check the source and target relations: a later filter is done by the  {@link 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[]} Return the supported operations between those two points. Order matters: after filtering that array, the first relation is considered as the default one.
     */
    _supportedRelations: function(sourceTargets, targetTargets)
    {
        var sourceMatch = Ametys.message.MessageTargetHelper.findTargets(sourceTargets, Ametys.message.MessageTarget.EXTRACTION_DEFINITION_FILE, 1),
            sourceContainerMatch = Ametys.message.MessageTargetHelper.findTargets(sourceTargets, Ametys.message.MessageTarget.EXTRACTION_DEFINITION_FOLDER, 1);
        if (sourceMatch.length == 0 && sourceContainerMatch.length == 0 
            || (sourceMatch.length + sourceContainerMatch.length) != sourceTargets.length)
        {
            return [];
        }
        
        var targetMatch = Ametys.message.MessageTargetHelper.findTargets(targetTargets, Ametys.message.MessageTarget.EXTRACTION_DEFINITION_FOLDER, 1);
        targetMatch = targetMatch.filter(
                function (target) 
                {
                    var parameters = target.parameters || target.getParameters();
            return parameters.canWrite;
          });
        if (targetMatch.length != 1)
        {
            return [];
        }

        var relations = [ 
            Ext.create('Ametys.relation.Relation', {
                type: Ametys.relation.Relation.MOVE,
                label: "{{i18n PLUGINS_EXTRACTION_RELATIONS_MOVE_EXTRACTION_DEFINITION_FILE_LABEL}}",
                description: "{{i18n PLUGINS_EXTRACTION_RELATIONS_MOVE_EXTRACTION_DEFINITION_FILE_DESCRIPTION}}"
            })
        ];
            
        return relations;
    },
    
    supportedRelations: function(source, target)
    {
        return this._supportedRelations(source.targets, target.targets);
    },
    
    /**
     * @private
     * 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 invoke a callback at the end.
     * In most cases this implementation will send a {@link Ametys.message.Message} to let the UI know that the operation is finished.
     * @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 {Function} callback The callback to call when the operation has ended. 
     * @param {Boolean} callback.success True if the operation was successful
     */
    _link: function(sourceTargets, target, callback)
    {
        var sourceQuery = Ametys.message.MessageTargetHelper.findTarget(sourceTargets, Ametys.message.MessageTarget.EXTRACTION_DEFINITION_FILE, 1),
            sourceQueryContainer = Ametys.message.MessageTargetHelper.findTarget(sourceTargets, Ametys.message.MessageTarget.EXTRACTION_DEFINITION_FOLDER, 1);
        
        if (sourceQuery)
        {
            this._move(sourceQuery, target, Ametys.message.MessageTarget.EXTRACTION_DEFINITION_FILE, callback);
        }
        else if (sourceQueryContainer)
        {
            this._move(sourceQueryContainer, target, Ametys.message.MessageTarget.EXTRACTION_DEFINITION_FOLDER, callback);
        }
        else
        {
            callback(false);
        }
    },
    
    link: function(source, target, callback, relationType)
    {
        this._link(source.getTargets(), target.getTarget(), callback);
    },
    
    /**
     * @private
     * Move a file or a folder to a target folder
     * @param {Ametys.message.MessageTarget} source 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 {String} type The type of element to move (Ametys.message.MessageTarget.PARAM_FILE or Ametys.message.MessageTarget.PARAM_FOLDER)
     * @param {Function} callback The callback function called when the folders has been moved
     * @param {String} callback.target The id of target
     * @param {String[]} callback.ids The ids of the moved folders.
     */
    _move: function(source, target, type, callback)
    {
        var newPathFolder = target.getParameters().nodePath != undefined ? target.getParameters().nodePath : target.getParameters().path;
        var oldPath = source.getParameters().nodePath != undefined ? source.getParameters().nodePath : source.getParameters().path;
        Ametys.data.ServerComm.callMethod({
            role: 'org.ametys.plugins.extraction.execution.ExtractionDAO',
            methodName: 'moveOrRenameExtractionDefinitionFile',
            parameters: [source.getParameters().path, target.getParameters().path + "/" + source.getParameters().name],
            callback: {
                handler: this._moveCb,
                scope: this,
                arguments: {
                    newPath: newPathFolder + (newPathFolder ? '/' : '') + source.getParameters().name, 
                    oldPath: oldPath, 
                    type: type, 
                    callback: callback,
                    messageTargetType: type,
                }
            },
            errorMessage: {
                msg: "{{i18n PLUGINS_EXTRACTION_RELATIONS_MOVE_EXTRACTION_DEFINITION_FILE_CANNOT_MOVE_MSG}}",
                category: this.self.getName()
            }
         });
        
    },
    
    /**
     * @private
     * Callback function invoked after moving objects
     * @param {Object} response The server result
     * @param {String} response.msg In case of error
     * @param {Object[]} args Additionnal arguments
     * @param {Function} [args.callback] A callback at the end
     * @param {String} [args.messageTargetType] The target type in #move
     * @param {String} [args.oldPath] The target path before #move
     * @param {String} [args.newPath] The target path after #move
     */
    _moveCb: function (response, args)
    {
        if (response.error && response.error == 'already-exists' && args.oldPath != args.newPath || response.error && response.error == 'no-exists')
        {
            Ametys.Msg.show({
                title: "{{i18n PLUGINS_EXTRACTION_RELATIONS_MOVE_EXTRACTION_DEFINITION_FILE_CANNOT_MOVE_TITLE}}",
                msg: "{{i18n PLUGINS_EXTRACTION_RELATIONS_MOVE_EXTRACTION_DEFINITION_FILE_CANNOT_MOVE_MSG}}",
                buttons: Ext.Msg.OK,
                icon: Ext.Msg.ERROR
            });
            
            if (Ext.isFunction(args.callback))
            {
                args.callback(false);
            }
            return false;
        }
        
        Ext.create("Ametys.message.Message", {
            type: Ametys.message.Message.MOVED,

            parameters: { 
                oldPath: args.oldPath
            },
            targets: {
                id: args.messageTargetType,
                parameters: { 
                    path: args.newPath
                }
            }
        });
                
        if (Ext.isFunction(args.callback))
        {
            args.callback(true);
        }
    }
});