/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */

/* global define, module, require, exports */

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        define(['d3',
                'nf.Connection',
                'nf.ConnectionConfiguration',
                'nf.CanvasUtils'],
            function (d3, nfConnection, nfConnectionConfiguration, nfCanvasUtils) {
                return (nf.Connectable = factory(d3, nfConnection, nfConnectionConfiguration, nfCanvasUtils));
            });
    } else if (typeof exports === 'object' && typeof module === 'object') {
        module.exports = (nf.Connectable =
            factory(require('d3'),
                require('nf.Connection'),
                require('nf.ConnectionConfiguration'),
                require('nf.CanvasUtils')));
    } else {
        nf.Connectable = factory(root.d3,
            root.nf.Connection,
            root.nf.ConnectionConfiguration,
            root.nf.CanvasUtils);
    }
}(this, function (d3, nfConnection, nfConnectionConfiguration, nfCanvasUtils) {
    'use strict';

    var connect;
    var canvas;
    var origin;

    var config = {
            urls: {
                api: '../nifi-api',
            }
        };

    /**
     * Determines if we want to allow adding connections in the current state:
     *
     * 1) When shift is down, we could be adding components to the current selection.
     * 2) When the selection box is visible, we are in the process of moving all the
     * components currently selected.
     * 3) When the drag selection box is visible, we are in the process or selecting components
     * using the selection box.
     *
     * @returns {boolean}
     */
    var allowConnection = function () {
        return !d3.event.shiftKey && d3.select('rect.drag-selection').empty() && d3.select('rect.component-selection').empty();
    };

    return {
        init: function () {
            canvas = d3.select('#canvas');

            // dragging behavior for the connector
            connect = d3.drag()
                .subject(function (d) {
                    origin = d3.mouse(canvas.node());
                    return {
                        x: origin[0],
                        y: origin[1]
                    };
                })
                .on('start', function (d) {
                    // stop further propagation
                    d3.event.sourceEvent.stopPropagation();

                    // unselect the previous components
                    nfCanvasUtils.getSelection().classed('selected', false);

                    // mark the source component has selected
                    var source = d3.select(this.parentNode).classed('selected', true);

                    // mark this component as dragging and selected
                    d3.select(this).classed('dragging', true);

                    // mark the source of the drag
                    var sourceData = source.datum();

                    // start the drag line and insert it first to keep it on the bottom
                    var position = d3.mouse(canvas.node());
                    canvas.insert('path', ':first-child')
                        .datum({
                            'sourceId': sourceData.id,
                            'sourceWidth': sourceData.dimensions.width,
                            'x': position[0],
                            'y': position[1]
                        })
                        .attrs({
                            'class': 'connector',
                            'd': function (pathDatum) {
                                return 'M' + pathDatum.x + ' ' + pathDatum.y + 'L' + pathDatum.x + ' ' + pathDatum.y;
                            }
                        });

                    // updates the location of the connection img
                    d3.select(this).attr('transform', function () {
                        return 'translate(' + position[0] + ', ' + (position[1] + 20) + ')';
                    });

                    // re-append the image to keep it on top
                    canvas.node().appendChild(this);
                })
                .on('drag', function (d) {
                    // updates the location of the connection img
                    d3.select(this).attr('transform', function () {
                        return 'translate(' + d3.event.x + ', ' + (d3.event.y + 50) + ')';
                    });

                    // mark node's connectable if supported
                    var destination = d3.select('g.hover').classed('connectable-destination', function () {
                        // ensure the mouse has moved at least 10px in any direction, it seems that
                        // when the drag event is trigger is not consistent between browsers. as a result
                        // some browser would trigger when the mouse hadn't moved yet which caused
                        // click and contextmenu events to appear like an attempt to connection the
                        // component to itself. requiring the mouse to have actually moved before
                        // checking the eligiblity of the destination addresses the issue
                        return (Math.abs(origin[0] - d3.event.x) > 10 || Math.abs(origin[1] - d3.event.y) > 10) &&
                            nfCanvasUtils.isValidConnectionDestination(d3.select(this));
                    });

                    // update the drag line
                    d3.select('path.connector').classed('connectable', function () {
                        if (destination.empty()) {
                            return false;
                        }

                        // if there is a potential destination, see if its connectable
                        return destination.classed('connectable-destination');
                    }).attr('d', function (pathDatum) {
                        if (!destination.empty() && destination.classed('connectable-destination')) {
                            var destinationData = destination.datum();

                            // show the line preview as appropriate
                            if (pathDatum.sourceId === destinationData.id) {
                                var x = pathDatum.x;
                                var y = pathDatum.y;
                                var componentOffset = pathDatum.sourceWidth / 2;
                                var xOffset = nfConnection.config.selfLoopXOffset;
                                var yOffset = nfConnection.config.selfLoopYOffset;
                                return 'M' + x + ' ' + y + 'L' + (x + componentOffset + xOffset) + ' ' + (y - yOffset) + 'L' + (x + componentOffset + xOffset) + ' ' + (y + yOffset) + 'Z';
                            } else {
                                // get the position on the destination perimeter
                                var end = nfCanvasUtils.getPerimeterPoint(pathDatum, {
                                    'x': destinationData.position.x,
                                    'y': destinationData.position.y,
                                    'width': destinationData.dimensions.width,
                                    'height': destinationData.dimensions.height
                                });

                                // direct line between components to provide a 'snap feel'
                                return 'M' + pathDatum.x + ' ' + pathDatum.y + 'L' + end.x + ' ' + end.y;
                            }
                        } else {
                            return 'M' + pathDatum.x + ' ' + pathDatum.y + 'L' + d3.event.x + ' ' + d3.event.y;
                        }
                    });
                })
                .on('end', function (d) {
                    // stop further propagation
                    d3.event.sourceEvent.stopPropagation();

                    // get the add connect img
                    var addConnect = d3.select(this);

                    // get the connector, if it the current point is not over a new destination
                    // the connector will be removed. otherwise it will be removed after the
                    // connection has been configured/cancelled
                    var connector = d3.select('path.connector');
                    var connectorData = connector.datum();

                    // get the destination
                    var destination = d3.select('g.connectable-destination');

                    // we are not over a new destination
                    if (destination.empty()) {
                        // get the source to determine if we are still over it
                        var source = d3.select('#id-' + connectorData.sourceId);
                        var sourceData = source.datum();

                        // get the mouse position relative to the source
                        var position = d3.mouse(source.node());

                        // if the position is outside the component, remove the add connect img
                        if (position[0] < 0 || position[0] > sourceData.dimensions.width || position[1] < 0 || position[1] > sourceData.dimensions.height) {
                            addConnect.remove();
                        } else {
                            // reset the add connect img by restoring the position and place in the DOM
                            addConnect.classed('dragging', false).attr('transform', function () {
                                return 'translate(' + d.origX + ', ' + d.origY + ')';
                            });
                            source.node().appendChild(this);
                        }

                        // remove the connector
                        connector.remove();
                    } else {
                        // remove the add connect img
                        addConnect.remove();

                        // create the connection
                        var destinationData = destination.datum();

                        $.ajax({
                            type: 'GET',
                            url: config.urls.api + '/process-groups/' + encodeURIComponent(destinationData.component.parentGroupId),
                            dataType: 'json'
                        }).done(function (response) {
                            var defaultSettings = {
                                flowfileExpiration: response.component.defaultFlowFileExpiration,
                                objectThreshold: response.component.defaultBackPressureObjectThreshold,
                                dataSizeThreshold: response.component.defaultBackPressureDataSizeThreshold,
                            };
                            nfConnectionConfiguration.createConnection(connectorData.sourceId, destinationData.id, defaultSettings);
                        });
                    }
                });
        },

        /**
         * Activates the connect behavior for the components in the specified selection.
         *
         * @param {selection} components
         */
        activate: function (components) {
            components
                .classed('connectable', true)
                .on('mouseenter.connectable', function (d) {
                    if (allowConnection()) {
                        var selection = d3.select(this);

                        // ensure the current component supports connection source
                        if (nfCanvasUtils.isValidConnectionSource(selection)) {
                            // see if theres already a connector rendered
                            var addConnect = d3.select('text.add-connect');
                            if (addConnect.empty()) {
                                var x = (d.dimensions.width / 2) - 14;
                                var y = (d.dimensions.height / 2) + 14;

                                selection.append('text')
                                    .datum({
                                        origX: x,
                                        origY: y
                                    })
                                    .call(connect)
                                    .attrs({
                                        'class': 'add-connect',
                                        'transform': 'translate(' + x + ', ' + y + ')'
                                    })
                                    .text('\ue834');
                            }
                        }
                    }
                })
                .on('mouseleave.connectable', function () {
                    // conditionally remove the connector
                    var addConnect = d3.select(this).select('text.add-connect');
                    if (!addConnect.empty() && !addConnect.classed('dragging')) {
                        addConnect.remove();
                    }
                })
                // Using mouseover/out to workaround chrome issue #122746
                .on('mouseover.connectable', function () {
                    // mark that we are hovering when appropriate
                    d3.select(this).classed('hover', function () {
                        return allowConnection();
                    });
                })
                .on('mouseout.connection', function () {
                    // remove all hover related classes
                    d3.select(this).classed('hover connectable-destination', false);
                });
        },

        /**
         * Deactivates the connect behavior for the components in the specified selection.
         *
         * @param {selection} components
         */
        deactivate: function (components) {
            components
                .classed('connectable', false)
                .on('mouseenter.connectable', null)
                .on('mouseleave.connectable', null)
                .on('mouseover.connectable', null)
                .on('mouseout.connectable', null);
        }
    };
}));
