/*
 * 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(['jquery',
                'd3',
                'nf.ErrorHandler',
                'nf.Common',
                'nf.Dialog',
                'nf.Storage',
                'nf.Client',
                'nf.CanvasUtils',
                'nf.Connection'],
            function ($, d3, nfErrorHandler, nfCommon, nfDialog, nfStorage, nfClient, nfCanvasUtils, nfConnection) {
                return (nf.ConnectionConfiguration = factory($, d3, nfErrorHandler, nfCommon, nfDialog, nfStorage, nfClient, nfCanvasUtils, nfConnection));
            });
    } else if (typeof exports === 'object' && typeof module === 'object') {
        module.exports = (nf.ConnectionConfiguration =
            factory(require('jquery'),
                require('d3'),
                require('nf.ErrorHandler'),
                require('nf.Common'),
                require('nf.Dialog'),
                require('nf.Storage'),
                require('nf.Client'),
                require('nf.CanvasUtils'),
                require('nf.Connection')));
    } else {
        nf.ConnectionConfiguration = factory(root.$,
            root.d3,
            root.nf.ErrorHandler,
            root.nf.Common,
            root.nf.Dialog,
            root.nf.Storage,
            root.nf.Client,
            root.nf.CanvasUtils,
            root.nf.Connection);
    }
}(this, function ($, d3, nfErrorHandler, nfCommon, nfDialog, nfStorage, nfClient, nfCanvasUtils, nfConnection) {
    'use strict';

    var nfBirdseye;
    var nfGraph;

    var defaultBackPressureObjectThreshold;
    var defaultBackPressureDataSizeThreshold;

    var CONNECTION_OFFSET_Y_INCREMENT = 75;
    var CONNECTION_OFFSET_X_INCREMENT = 200;

    var connectionUpsertionInProgress = false;

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

    /**
     * Removes the temporary if necessary.
     */
    var removeTempEdge = function () {
        d3.select('path.connector').remove();
    };

    /**
     * Activates dialog's button model refresh on a connection relationships change.
     */
    var addDialogRelationshipsChangeListener = function() {
        // refresh button model when a relationship selection changes
        $('div.available-relationship').bind('change', function() {
            $('#connection-configuration').modal('refreshButtons');
        });
    }

    /**
     * Initializes the source in the new connection dialog.
     *
     * @argument {selection} source        The source
     */
    var initializeSourceNewConnectionDialog = function (source) {
        // handle the selected source
        if (nfCanvasUtils.isProcessor(source)) {
            return $.Deferred(function (deferred) {
                // initialize the source processor
                initializeSourceProcessor(source).done(function (processor) {
                    if (!nfCommon.isEmpty(processor.relationships)) {
                        // populate the available connections
                        $.each(processor.relationships, function (i, relationship) {
                            createRelationshipOption(relationship.name);
                        });
                        
                        addDialogRelationshipsChangeListener();

                        // if there is a single relationship auto select
                        var relationships = $('#relationship-names').children('div');
                        if (relationships.length === 1) {
                            relationships.children('div.available-relationship').removeClass('checkbox-unchecked').addClass('checkbox-checked');
                        }

                        // configure the button model
                        $('#connection-configuration').modal('setButtonModel', [{
                            buttonText: 'Add',
                            color: {
                                base: '#728E9B',
                                hover: '#004849',
                                text: '#ffffff'
                            },
                            disabled: function () {
                                // ensure some relationships were selected, also check create or updation in progress
                                return getSelectedRelationships().length === 0 || isConnectionUpsertionInProgess();
                            },
                            handler: {
                                click: function () {
                                    addConnection(getSelectedRelationships());
                                }
                            }
                        },
                            {
                                buttonText: 'Cancel',
                                color: {
                                    base: '#E3E8EB',
                                    hover: '#C7D2D7',
                                    text: '#004849'
                                },
                                disabled: function() {
                                    // when add button is clicked, should disable until the addition action is completed
                                    return isConnectionUpsertionInProgess();
                                },
                                handler: {
                                    click: function () {
                                        $('#connection-configuration').modal('hide');
                                    }
                                }
                            }]);

                        // resolve the deferred
                        deferred.resolve();
                    } else {
                        // there are no relationships for this processor
                        nfDialog.showOkDialog({
                            headerText: 'Connection Configuration',
                            dialogContent: '\'' + nfCommon.escapeHtml(processor.name) + '\' does not support any relationships.'
                        });

                        // reset the dialog
                        resetDialog();

                        deferred.reject();
                    }
                }).fail(function () {
                    deferred.reject();
                });
            }).promise();
        } else {
            return $.Deferred(function (deferred) {
                // determine how to initialize the source
                var connectionSourceDeferred;
                if (nfCanvasUtils.isInputPort(source)) {
                    connectionSourceDeferred = initializeSourceInputPort(source);
                } else if (nfCanvasUtils.isRemoteProcessGroup(source)) {
                    connectionSourceDeferred = initializeSourceRemoteProcessGroup(source);
                } else if (nfCanvasUtils.isProcessGroup(source)) {
                    connectionSourceDeferred = initializeSourceProcessGroup(source);
                } else {
                    connectionSourceDeferred = initializeSourceFunnel(source);
                }

                // finish initialization when appropriate
                connectionSourceDeferred.done(function () {
                    // configure the button model
                    $('#connection-configuration').modal('setButtonModel', [{
                        buttonText: 'Add',
                        color: {
                            base: '#728E9B',
                            hover: '#004849',
                            text: '#ffffff'
                        },
                        disabled : function(){
                            // when network is slow, should disable the button
                            return isConnectionUpsertionInProgess();
                        },
                        handler: {
                            click: function () {
                                // add the connection
                                addConnection();
                            }
                        }
                    },
                        {
                            buttonText: 'Cancel',
                            color: {
                                base: '#E3E8EB',
                                hover: '#C7D2D7',
                                text: '#004849'
                            },
                            disabled : function(){
                                return isConnectionUpsertionInProgess();
                            },
                            handler: {
                                click: function () {
                                    $('#connection-configuration').modal('hide');
                                }
                            }
                        }]);

                    deferred.resolve();
                }).fail(function () {
                    deferred.reject();
                });
            }).promise();
        }
    };

    /**
     * Initializes the source when the source is an input port.
     *
     * @argument {selection} source        The source
     */
    var initializeSourceInputPort = function (source) {
        return $.Deferred(function (deferred) {
            // get the input port data
            var inputPortData = source.datum();
            var inputPortName = inputPortData.permissions.canRead ? inputPortData.component.name : inputPortData.id;

            // populate the port information
            $('#input-port-source').show();
            $('#input-port-source-name').text(inputPortName).attr('title', inputPortName);

            // populate the connection source details
            $('#connection-source-id').val(inputPortData.id);
            $('#connection-source-component-id').val(inputPortData.id);

            // populate the group details
            $('#connection-source-group-id').val(nfCanvasUtils.getGroupId());
            $('#connection-source-group-name').text(nfCanvasUtils.getGroupName());

            // resolve the deferred
            deferred.resolve();
        }).promise();
    };

    /**
     * Initializes the source when the source is an input port.
     *
     * @argument {selection} source        The source
     */
    var initializeSourceFunnel = function (source) {
        return $.Deferred(function (deferred) {
            // get the funnel data
            var funnelData = source.datum();

            // populate the port information
            $('#funnel-source').show();

            // populate the connection source details
            $('#connection-source-id').val(funnelData.id);
            $('#connection-source-component-id').val(funnelData.id);

            // populate the group details
            $('#connection-source-group-id').val(nfCanvasUtils.getGroupId());
            $('#connection-source-group-name').text(nfCanvasUtils.getGroupName());

            // resolve the deferred
            deferred.resolve();
        }).promise();
    };

    /**
     * Initializes the source when the source is a processor.
     *
     * @argument {selection} source        The source
     */
    var initializeSourceProcessor = function (source) {
        return $.Deferred(function (deferred) {
            // get the processor data
            var processorData = source.datum();
            var processorName = processorData.permissions.canRead ? processorData.component.name : processorData.id;
            var processorType = processorData.permissions.canRead ? nfCommon.substringAfterLast(processorData.component.type, '.') : 'Processor';

            // populate the source processor information
            $('#processor-source').show();
            $('#processor-source-name').text(processorName).attr('title', processorName);
            $('#processor-source-type').text(processorType).attr('title', processorType);

            // populate the connection source details
            $('#connection-source-id').val(processorData.id);
            $('#connection-source-component-id').val(processorData.id);

            // populate the group details
            $('#connection-source-group-id').val(nfCanvasUtils.getGroupId());
            $('#connection-source-group-name').text(nfCanvasUtils.getGroupName());

            // show the available relationships
            $('#relationship-names-container').show();

            deferred.resolve(processorData.component);
        });
    };

    /**
     * Initializes the source when the source is a process group.
     *
     * @argument {selection} source        The source
     */
    var initializeSourceProcessGroup = function (source) {
        return $.Deferred(function (deferred) {
            // get the process group data
            var processGroupData = source.datum();

            $.ajax({
                type: 'GET',
                url: config.urls.api + '/flow/process-groups/' + encodeURIComponent(processGroupData.id),
                dataType: 'json'
            }).done(function (response) {
                var processGroup = response.processGroupFlow;
                var processGroupName = response.permissions.canRead ? processGroup.breadcrumb.breadcrumb.name : processGroup.id;
                var processGroupContents = processGroup.flow;

                // show the output port options
                var options = [];
                var publicOutputPortCount = 0;
                $.each(processGroupContents.outputPorts, function (i, outputPort) {
                    if (outputPort.allowRemoteAccess) {
                        publicOutputPortCount++;
                        return;
                    }
                    // require explicit access to the output port as it's the source of the connection
                    if (outputPort.permissions.canRead && outputPort.permissions.canWrite) {
                        var component = outputPort.component;
                        options.push({
                            text: component.name,
                            value: component.id,
                            description: nfCommon.escapeHtml(component.comments)
                        });
                    }
                });

                // only proceed if there are output ports
                if (!nfCommon.isEmpty(options)) {
                    $('#output-port-source').show();

                    // sort the options
                    options.sort(function (a, b) {
                        return a.text.localeCompare(b.text);
                    });

                    // create the combo
                    $('#output-port-options').combo({
                        options: options,
                        maxHeight: 300,
                        select: function (option) {
                            $('#connection-source-id').val(option.value);
                        }
                    });

                    // populate the connection details
                    $('#connection-source-component-id').val(processGroup.id);

                    // populate the group details
                    $('#connection-source-group-id').val(processGroup.id);
                    $('#connection-source-group-name').text(processGroupName);

                    deferred.resolve();
                } else {
                    var message = '\'' + nfCommon.escapeHtml(processGroupName) + '\' does not have any local output ports.';
                    if (nfCommon.isEmpty(processGroupContents.outputPorts) === false
                            && processGroupContents.outputPorts.length > publicOutputPortCount) {
                        message = 'Not authorized for any local output ports in \'' + nfCommon.escapeHtml(processGroupName) + '\'.';
                    }

                    // there are no output ports for this process group
                    nfDialog.showOkDialog({
                        headerText: 'Connection Configuration',
                        dialogContent: message
                    });

                    // reset the dialog
                    resetDialog();

                    deferred.reject();
                }
            }).fail(function (xhr, status, error) {
                // handle the error
                nfErrorHandler.handleAjaxError(xhr, status, error);

                deferred.reject();
            });
        }).promise();
    };

    /**
     * Initializes the source when the source is a remote process group.
     *
     * @argument {selection} source        The source
     */
    var initializeSourceRemoteProcessGroup = function (source) {
        return $.Deferred(function (deferred) {
            // get the remote process group data
            var remoteProcessGroupData = source.datum();

            $.ajax({
                type: 'GET',
                url: remoteProcessGroupData.uri,
                dataType: 'json'
            }).done(function (response) {
                var remoteProcessGroup = response.component;
                var remoteProcessGroupContents = remoteProcessGroup.contents;

                // only proceed if there are output ports
                if (!nfCommon.isEmpty(remoteProcessGroupContents.outputPorts)) {
                    $('#output-port-source').show();

                    // show the output port options
                    var options = [];
                    $.each(remoteProcessGroupContents.outputPorts, function (i, outputPort) {
                        options.push({
                            text: outputPort.name,
                            value: outputPort.id,
                            disabled: outputPort.exists === false,
                            description: nfCommon.escapeHtml(outputPort.comments)
                        });
                    });

                    // sort the options
                    options.sort(function (a, b) {
                        return a.text.localeCompare(b.text);
                    });

                    // create the combo
                    $('#output-port-options').combo({
                        options: options,
                        maxHeight: 300,
                        select: function (option) {
                            $('#connection-source-id').val(option.value);
                        }
                    });

                    // populate the connection details
                    $('#connection-source-component-id').val(remoteProcessGroup.id);

                    // populate the group details
                    $('#connection-source-group div.setting-name').text('Within Remote Group')
                    $('#connection-remote-source-url').text(remoteProcessGroup.targetUri).show();
                    $('#connection-source-group-id').val(remoteProcessGroup.id);
                    $('#connection-source-group-name').text(remoteProcessGroup.name);

                    deferred.resolve();
                } else {
                    // there are no relationships for this processor
                    nfDialog.showOkDialog({
                        headerText: 'Connection Configuration',
                        dialogContent: '\'' + nfCommon.escapeHtml(remoteProcessGroup.name) + '\' does not have any output ports.'
                    });

                    // reset the dialog
                    resetDialog();

                    deferred.reject();
                }
            }).fail(function (xhr, status, error) {
                // handle the error
                nfErrorHandler.handleAjaxError(xhr, status, error);

                deferred.reject();
            });
        }).promise();
    };

    var initializeDestinationNewConnectionDialog = function (destination) {
        if (nfCanvasUtils.isOutputPort(destination)) {
            return initializeDestinationOutputPort(destination);
        } else if (nfCanvasUtils.isProcessor(destination)) {
            return initializeDestinationProcessor(destination);
        } else if (nfCanvasUtils.isRemoteProcessGroup(destination)) {
            return initializeDestinationRemoteProcessGroup(destination);
        } else if (nfCanvasUtils.isFunnel(destination)) {
            return initializeDestinationFunnel(destination);
        } else {
            return initializeDestinationProcessGroup(destination);
        }
    };

    var initializeDestinationOutputPort = function (destination) {
        return $.Deferred(function (deferred) {
            var outputPortData = destination.datum();
            var outputPortName = outputPortData.permissions.canRead ? outputPortData.component.name : outputPortData.id;

            $('#output-port-destination').show();
            $('#output-port-destination-name').text(outputPortName).attr('title', outputPortName);

            // populate the connection destination details
            $('#connection-destination-id').val(outputPortData.id);
            $('#connection-destination-component-id').val(outputPortData.id);

            // populate the group details
            $('#connection-destination-group-id').val(nfCanvasUtils.getGroupId());
            $('#connection-destination-group-name').text(nfCanvasUtils.getGroupName());

            deferred.resolve();
        }).promise();
    };

    var initializeDestinationFunnel = function (destination) {
        return $.Deferred(function (deferred) {
            var funnelData = destination.datum();

            $('#funnel-destination').show();

            // populate the connection destination details
            $('#connection-destination-id').val(funnelData.id);
            $('#connection-destination-component-id').val(funnelData.id);

            // populate the group details
            $('#connection-destination-group-id').val(nfCanvasUtils.getGroupId());
            $('#connection-destination-group-name').text(nfCanvasUtils.getGroupName());

            deferred.resolve();
        }).promise();
    };

    var initializeDestinationProcessor = function (destination) {
        return $.Deferred(function (deferred) {
            var processorData = destination.datum();
            var processorName = processorData.permissions.canRead ? processorData.component.name : processorData.id;
            var processorType = processorData.permissions.canRead ? nfCommon.substringAfterLast(processorData.component.type, '.') : 'Processor';

            $('#processor-destination').show();
            $('#processor-destination-name').text(processorName).attr('title', processorName);
            $('#processor-destination-type').text(processorType).attr('title', processorType);

            // populate the connection destination details
            $('#connection-destination-id').val(processorData.id);
            $('#connection-destination-component-id').val(processorData.id);

            // populate the group details
            $('#connection-destination-group-id').val(nfCanvasUtils.getGroupId());
            $('#connection-destination-group-name').text(nfCanvasUtils.getGroupName());

            deferred.resolve();
        }).promise();
    };

    /**
     * Initializes the destination when the destination is a process group.
     *
     * @argument {selection} destination        The destination
     */
    var initializeDestinationProcessGroup = function (destination) {
        return $.Deferred(function (deferred) {
            var processGroupData = destination.datum();

            $.ajax({
                type: 'GET',
                url: config.urls.api + '/flow/process-groups/' + encodeURIComponent(processGroupData.id),
                dataType: 'json'
            }).done(function (response) {
                var processGroup = response.processGroupFlow;
                var processGroupName = response.permissions.canRead ? processGroup.breadcrumb.breadcrumb.name : processGroup.id;
                var processGroupContents = processGroup.flow;

                // show the input port options
                var options = [];
                $.each(processGroupContents.inputPorts, function (i, inputPort) {
                    if (!inputPort.allowRemoteAccess) {
                        options.push({
                            text: inputPort.permissions.canRead ? inputPort.component.name : inputPort.id,
                            value: inputPort.id,
                            description: inputPort.permissions.canRead ? nfCommon.escapeHtml(inputPort.component.comments) : null
                        });
                    }
                });

                // only proceed if there are output ports
                if (!nfCommon.isEmpty(options)) {
                    $('#input-port-destination').show();

                    // sort the options
                    options.sort(function (a, b) {
                        return a.text.localeCompare(b.text);
                    });

                    // create the combo
                    $('#input-port-options').combo({
                        options: options,
                        maxHeight: 300,
                        select: function (option) {
                            $('#connection-destination-id').val(option.value);
                        }
                    });

                    // populate the connection details
                    $('#connection-destination-component-id').val(processGroup.id);

                    // populate the group details
                    $('#connection-destination-group-id').val(processGroup.id);
                    $('#connection-destination-group-name').text(processGroupName);

                    deferred.resolve();
                } else {
                    // there are no relationships for this processor
                    nfDialog.showOkDialog({
                        headerText: 'Connection Configuration',
                        dialogContent: '\'' + nfCommon.escapeHtml(processGroupName) + '\' does not have any local input ports.'
                    });

                    // reset the dialog
                    resetDialog();

                    deferred.reject();
                }
            }).fail(function (xhr, status, error) {
                // handle the error
                nfErrorHandler.handleAjaxError(xhr, status, error);

                deferred.reject();
            });
        }).promise();
    };

    /**
     * Initializes the source when the source is a remote process group.
     *
     * @argument {selection} destination        The destination
     * @argument {object} connectionDestination The connection destination object
     */
    var initializeDestinationRemoteProcessGroup = function (destination, connectionDestination) {
        return $.Deferred(function (deferred) {
            var remoteProcessGroupData = destination.datum();

            $.ajax({
                type: 'GET',
                url: remoteProcessGroupData.uri,
                dataType: 'json'
            }).done(function (response) {
                var remoteProcessGroup = response.component;
                var remoteProcessGroupContents = remoteProcessGroup.contents;

                // only proceed if there are output ports
                if (!nfCommon.isEmpty(remoteProcessGroupContents.inputPorts)) {
                    $('#input-port-destination').show();

                    // show the input port options
                    var options = [];
                    $.each(remoteProcessGroupContents.inputPorts, function (i, inputPort) {
                        options.push({
                            text: inputPort.name,
                            value: inputPort.id,
                            disabled: inputPort.exists === false,
                            description: nfCommon.escapeHtml(inputPort.comments)
                        });
                    });

                    // sort the options
                    options.sort(function (a, b) {
                        return a.text.localeCompare(b.text);
                    });

                    // create the combo
                    $('#input-port-options').combo({
                        options: options,
                        maxHeight: 300,
                        select: function (option) {
                            $('#connection-destination-id').val(option.value);
                        }
                    });

                    // populate the connection details
                    $('#connection-destination-component-id').val(remoteProcessGroup.id);

                    // populate the group details
                    $('#connection-destination-group div.setting-name').text('Within Remote Group')
                    $('#connection-remote-destination-url').text(remoteProcessGroup.targetUri).show();
                    $('#connection-destination-group-id').val(remoteProcessGroup.id);
                    $('#connection-destination-group-name').text(remoteProcessGroup.name);

                    deferred.resolve();
                } else {
                    // there are no relationships for this processor
                    nfDialog.showOkDialog({
                        headerText: 'Connection Configuration',
                        dialogContent: '\'' + nfCommon.escapeHtml(remoteProcessGroup.name) + '\' does not have any input ports.'
                    });

                    // reset the dialog
                    resetDialog();

                    deferred.reject();
                }
            }).fail(function (xhr, status, error) {
                // handle the error
                nfErrorHandler.handleAjaxError(xhr, status, error);

                deferred.reject();
            });
        }).promise();
    };

    /**
     * Initializes the source panel for groups.
     *
     * @argument {selection} source    The source of the connection
     */
    var initializeSourceReadOnlyGroup = function (source) {
        return $.Deferred(function (deferred) {
            var sourceData = source.datum();
            var sourceName = sourceData.permissions.canRead ? sourceData.component.name : sourceData.id;

            // populate the port information
            $('#read-only-output-port-source').show();

            // populate the component information
            $('#connection-source-component-id').val(sourceData.id);

            // populate the group details
            $('#connection-source-group-id').val(sourceData.id);
            $('#connection-source-group-name').text(sourceName);

            if (nfCanvasUtils.isRemoteProcessGroup(source)) {
                $('#connection-source-group div.setting-name').text('Within Remote Group');
                if (sourceData.permissions.canRead) {
                    $('#connection-remote-source-url').text(sourceData.component.targetUri).show();
                }
            }

            // resolve the deferred
            deferred.resolve();
        }).promise();
    };

    /**
     * Initializes the source in the existing connection dialog.
     *
     * @argument {selection} source        The source
     */
    var initializeSourceEditConnectionDialog = function (source) {
        if (nfCanvasUtils.isProcessor(source)) {
            return initializeSourceProcessor(source);
        } else if (nfCanvasUtils.isInputPort(source)) {
            return initializeSourceInputPort(source);
        } else if (nfCanvasUtils.isFunnel(source)) {
            return initializeSourceFunnel(source);
        } else {
            return initializeSourceReadOnlyGroup(source);
        }
    };

    /**
     * Initializes the destination in the existing connection dialog.
     *
     * @argument {selection} destination        The destination
     * @argument {object} connectionDestination The connection destination object
     */
    var initializeDestinationEditConnectionDialog = function (destination, connectionDestination) {
        if (nfCanvasUtils.isProcessor(destination)) {
            return initializeDestinationProcessor(destination);
        } else if (nfCanvasUtils.isOutputPort(destination)) {
            return initializeDestinationOutputPort(destination);
        } else if (nfCanvasUtils.isRemoteProcessGroup(destination)) {
            return initializeDestinationRemoteProcessGroup(destination, connectionDestination);
        } else if (nfCanvasUtils.isFunnel(destination)) {
            return initializeDestinationFunnel(destination);
        } else {
            return initializeDestinationProcessGroup(destination);
        }
    };

    /**
     * Creates an option for the specified relationship name.
     *
     * @argument {string} name      The relationship name
     */
    var createRelationshipOption = function (name) {
        var relationshipLabel = $('<div class="relationship-name nf-checkbox-label ellipsis"></div>').text(name);
        var relationshipValue = $('<span class="relationship-name-value hidden"></span>').text(name);
        return $('<div class="available-relationship-container"><div class="available-relationship nf-checkbox checkbox-unchecked"></div>' +
            '</div>').append(relationshipLabel).append(relationshipValue).appendTo('#relationship-names');
    };

    /**
     * To set or reset the connection addition/update in progress
     * @param {boolean} status the status of connection addition/update
     */
    var setConnectionUpsertionInProgess = function(status)
    {        
        var needToUpdateDOM = (connectionUpsertionInProgress !== status) ;
        connectionUpsertionInProgress = status;
        if(needToUpdateDOM){
            $('#connection-configuration').modal('refreshButtons');
        }
    }

    /**
     * returns whether the connection addition/update in progress
     */
    var isConnectionUpsertionInProgess = function()
    {        
        return connectionUpsertionInProgress;
    }

    /**
     * Adds a new connection.
     *
     * @argument {array} selectedRelationships      The selected relationships
     */
    var addConnection = function (selectedRelationships) {
        // to handle the case of slow network
        //the add/cancel buttons should be disabled
        setConnectionUpsertionInProgess(true);

        // get the connection details
        var sourceId = $('#connection-source-id').val();
        var destinationId = $('#connection-destination-id').val();

        // get the selection components
        var sourceComponentId = $('#connection-source-component-id').val();
        var source = d3.select('#id-' + sourceComponentId);
        var destinationComponentId = $('#connection-destination-component-id').val();
        var destination = d3.select('#id-' + destinationComponentId);

        // get the source/destination data
        var sourceData = source.datum();
        var destinationData = destination.datum();

        // add bend points if we're dealing with a self loop
        var bends = [];
        if (sourceComponentId === destinationComponentId) {
            var rightCenter = {
                x: sourceData.position.x + (sourceData.dimensions.width),
                y: sourceData.position.y + (sourceData.dimensions.height / 2)
            };

            var xOffset = nfConnection.config.selfLoopXOffset;
            var yOffset = nfConnection.config.selfLoopYOffset;
            bends.push({
                'x': (rightCenter.x + xOffset),
                'y': (rightCenter.y - yOffset)
            });
            bends.push({
                'x': (rightCenter.x + xOffset),
                'y': (rightCenter.y + yOffset)
            });
        } else {
            var existingConnections = [];

            // get all connections for the source component
            var connectionsForSourceComponent = nfConnection.getComponentConnections(sourceComponentId);
            $.each(connectionsForSourceComponent, function (_, connectionForSourceComponent) {
                // get the id for the source/destination component
                var connectionSourceComponentId = nfCanvasUtils.getConnectionSourceComponentId(connectionForSourceComponent);
                var connectionDestinationComponentId = nfCanvasUtils.getConnectionDestinationComponentId(connectionForSourceComponent);

                // if the connection is between these same components, consider it for collisions
                if ((connectionSourceComponentId === sourceComponentId && connectionDestinationComponentId === destinationComponentId) ||
                    (connectionDestinationComponentId === sourceComponentId && connectionSourceComponentId === destinationComponentId)) {

                    // record all connections between these two components in question
                    existingConnections.push(connectionForSourceComponent);
                }
            });

            // if there are existing connections between these components, ensure the new connection won't collide
            if (existingConnections.length > 0) {
                var avoidCollision = false;
                $.each(existingConnections, function (_, existingConnection) {
                    // only consider multiple connections with no bend points a collision, the existance of 
                    // bend points suggests that the user has placed the connection into a desired location
                    if (nfCommon.isEmpty(existingConnection.bends)) {
                        avoidCollision = true;
                        return false;
                    }
                });

                // if we need to avoid a collision
                if (avoidCollision === true) {
                    // determine the middle of the source/destination components
                    var sourceMiddle = [sourceData.position.x + (sourceData.dimensions.width / 2), sourceData.position.y + (sourceData.dimensions.height / 2)];
                    var destinationMiddle = [destinationData.position.x + (destinationData.dimensions.width / 2), destinationData.position.y + (destinationData.dimensions.height / 2)];

                    // detect if the line is more horizontal or vertical
                    var slope = ((sourceMiddle[1] - destinationMiddle[1]) / (sourceMiddle[0] - destinationMiddle[0]));
                    var isMoreHorizontal = slope <= 1 && slope >= -1;

                    // determines if the specified coordinate collides with another connection
                    var collides = function (x, y) {
                        var collides = false;
                        $.each(existingConnections, function (_, existingConnection) {
                            if (!nfCommon.isEmpty(existingConnection.bends)) {
                                if (isMoreHorizontal) {
                                    // horizontal lines are adjusted in the y space
                                    if (existingConnection.bends[0].y === y) {
                                        collides = true;
                                        return false;
                                    }
                                } else {
                                    // vertical lines are adjusted in the x space
                                    if (existingConnection.bends[0].x === x) {
                                        collides = true;
                                        return false;
                                    }
                                }
                            }
                        });
                        return collides;
                    };

                    // find the mid point on the connection
                    var xCandidate = (sourceMiddle[0] + destinationMiddle[0]) / 2;
                    var yCandidate = (sourceMiddle[1] + destinationMiddle[1]) / 2;

                    // attempt to position this connection so it doesn't collide
                    var xStep = isMoreHorizontal ? 0 : CONNECTION_OFFSET_X_INCREMENT;
                    var yStep = isMoreHorizontal ? CONNECTION_OFFSET_Y_INCREMENT : 0;
                    var positioned = false;
                    while (positioned === false) {
                        // consider above and below, then increment and try again (if necessary)
                        if (collides(xCandidate - xStep, yCandidate - yStep) === false) {
                            bends.push({
                                'x': (xCandidate - xStep),
                                'y': (yCandidate - yStep)
                            });
                            positioned = true;
                        } else if (collides(xCandidate + xStep, yCandidate + yStep) === false) {
                            bends.push({
                                'x': (xCandidate + xStep),
                                'y': (yCandidate + yStep)
                            });
                            positioned = true;
                        }

                        if (isMoreHorizontal) {
                            yStep += CONNECTION_OFFSET_Y_INCREMENT;
                        } else {
                            xStep += CONNECTION_OFFSET_X_INCREMENT;
                        }
                    }
                }
            }
        }

        // determine the source group id
        var sourceGroupId = $('#connection-source-group-id').val();
        var destinationGroupId = $('#connection-destination-group-id').val();

        // determine the source and destination types
        var sourceType = nfCanvasUtils.getConnectableTypeForSource(source);
        var destinationType = nfCanvasUtils.getConnectableTypeForDestination(destination);

        // get the settings
        var connectionName = $('#connection-name').val();
        var flowFileExpiration = $('#flow-file-expiration').val();
        var backPressureObjectThreshold = $('#back-pressure-object-threshold').val();
        var backPressureDataSizeThreshold = $('#back-pressure-data-size-threshold').val();
        var prioritizers = $('#prioritizer-selected').sortable('toArray');
        var loadBalanceStrategy = $('#load-balance-strategy-combo').combo('getSelectedOption').value;
        var shouldLoadBalance = 'DO_NOT_LOAD_BALANCE' !== loadBalanceStrategy;
        var loadBalancePartitionAttribute = shouldLoadBalance && 'PARTITION_BY_ATTRIBUTE' === loadBalanceStrategy ? $('#load-balance-partition-attribute').val() : '';
        var loadBalanceCompression = shouldLoadBalance ? $('#load-balance-compression-combo').combo('getSelectedOption').value : 'DO_NOT_COMPRESS';

        if (validateSettings()) {
            var connectionEntity = {
                'revision': nfClient.getRevision({
                    'revision': {
                        'version': 0
                    }
                }),
                'disconnectedNodeAcknowledged': nfStorage.isDisconnectionAcknowledged(),
                'component': {
                    'name': connectionName,
                    'source': {
                        'id': sourceId,
                        'groupId': sourceGroupId,
                        'type': sourceType
                    },
                    'destination': {
                        'id': destinationId,
                        'groupId': destinationGroupId,
                        'type': destinationType
                    },
                    'selectedRelationships': selectedRelationships,
                    'flowFileExpiration': flowFileExpiration,
                    'backPressureDataSizeThreshold': backPressureDataSizeThreshold,
                    'backPressureObjectThreshold': backPressureObjectThreshold,
                    'bends': bends,
                    'prioritizers': prioritizers,
                    'loadBalanceStrategy': loadBalanceStrategy,
                    'loadBalancePartitionAttribute': loadBalancePartitionAttribute,
                    'loadBalanceCompression': loadBalanceCompression
                }
            };

            // create the new connection
            $.ajax({
                type: 'POST',
                url: config.urls.api + '/process-groups/' + encodeURIComponent(nfCanvasUtils.getGroupId()) + '/connections',
                data: JSON.stringify(connectionEntity),
                dataType: 'json',
                contentType: 'application/json'
            }).done(function (response) {
                // add the connection
                nfGraph.add({
                    'connections': [response]
                }, {
                    'selectAll': true
                });

                setConnectionUpsertionInProgess(false);

                // close the dialog
                $('#connection-configuration').modal('hide');

                // reload the connections source/destination components
                nfCanvasUtils.reloadConnectionSourceAndDestination(sourceComponentId, destinationComponentId);

                // update component visibility
                nfGraph.updateVisibility();

                // update the birdseye
                nfBirdseye.refresh();
            }).fail(function(xhr, status, error){

                // update the button status 
                setConnectionUpsertionInProgess(false);
                nfErrorHandler.handleConfigurationUpdateAjaxError(xhr, status, error);
            });
        }
    };

    /**
     * Updates an existing connection.
     *
     * @argument {array} selectedRelationships          The selected relationships
     */
    var updateConnection = function (selectedRelationships) {
        //apply, cancel buttons should be disabled, while the connection update is in progress
        setConnectionUpsertionInProgess(true);

        // get the connection details
        var connectionId = $('#connection-id').text();
        var connectionUri = $('#connection-uri').val();

        // get the source details
        var sourceComponentId = $('#connection-source-component-id').val();

        // get the destination details
        var destinationComponentId = $('#connection-destination-component-id').val();
        var destination = d3.select('#id-' + destinationComponentId);
        var destinationType = nfCanvasUtils.getConnectableTypeForDestination(destination);

        // get the destination details
        var destinationId = $('#connection-destination-id').val();
        var destinationGroupId = $('#connection-destination-group-id').val();

        // get the settings
        var connectionName = $('#connection-name').val();
        var flowFileExpiration = $('#flow-file-expiration').val();
        var backPressureObjectThreshold = $('#back-pressure-object-threshold').val();
        var backPressureDataSizeThreshold = $('#back-pressure-data-size-threshold').val();
        var prioritizers = $('#prioritizer-selected').sortable('toArray');
        var loadBalanceStrategy = $('#load-balance-strategy-combo').combo('getSelectedOption').value;
        var shouldLoadBalance = 'DO_NOT_LOAD_BALANCE' !== loadBalanceStrategy;
        var loadBalancePartitionAttribute = shouldLoadBalance && 'PARTITION_BY_ATTRIBUTE' === loadBalanceStrategy ? $('#load-balance-partition-attribute').val() : '';
        var loadBalanceCompression = shouldLoadBalance ? $('#load-balance-compression-combo').combo('getSelectedOption').value : 'DO_NOT_COMPRESS';

        if (validateSettings()) {
            var d = nfConnection.get(connectionId);
            var connectionEntity = {
                'revision': nfClient.getRevision(d),
                'disconnectedNodeAcknowledged': nfStorage.isDisconnectionAcknowledged(),
                'component': {
                    'id': connectionId,
                    'name': connectionName,
                    'destination': {
                        'id': destinationId,
                        'groupId': destinationGroupId,
                        'type': destinationType
                    },
                    'selectedRelationships': selectedRelationships,
                    'flowFileExpiration': flowFileExpiration,
                    'backPressureDataSizeThreshold': backPressureDataSizeThreshold,
                    'backPressureObjectThreshold': backPressureObjectThreshold,
                    'prioritizers': prioritizers,
                    'loadBalanceStrategy': loadBalanceStrategy,
                    'loadBalancePartitionAttribute': loadBalancePartitionAttribute,
                    'loadBalanceCompression': loadBalanceCompression
                }
            };

            // update the connection
            return $.ajax({
                type: 'PUT',
                url: connectionUri,
                data: JSON.stringify(connectionEntity),
                dataType: 'json',
                contentType: 'application/json'
            }).done(function (response) {
                //update updation progress status
                setConnectionUpsertionInProgess(false);

                // close the dialog
                $('#connection-configuration').modal('hide');

                // update this connection
                nfConnection.set(response);

                // reload the connections source/destination components
                nfCanvasUtils.reloadConnectionSourceAndDestination(sourceComponentId, destinationComponentId);
            }).fail(function(xhr, status, error){
                setConnectionUpsertionInProgess(false);
                nfErrorHandler.handleConfigurationUpdateAjaxError(xhr, status, error);
            });
        } else {
            return $.Deferred(function (deferred) {
                deferred.reject();
            }).promise();
        }
    };

    /**
     * Returns an array of selected relationship names.
     */
    var getSelectedRelationships = function () {
        // get all available relationships
        var availableRelationships = $('#relationship-names');
        var selectedRelationships = [];

        // go through each relationship to determine which are selected
        $.each(availableRelationships.children(), function (i, relationshipElement) {
            var relationship = $(relationshipElement);

            // get each relationship and its corresponding checkbox
            var relationshipCheck = relationship.children('div.available-relationship');

            // see if this relationship has been selected
            if (relationshipCheck.hasClass('checkbox-checked')) {
                selectedRelationships.push(relationship.children('span.relationship-name-value').text());
            }
        });

        return selectedRelationships;
    };

    /**
     * Validates the specified settings.
     */
    var validateSettings = function () {
        var errors = [];

        // validate the settings
        if (nfCommon.isBlank($('#flow-file-expiration').val())) {
            errors.push('File expiration must be specified');
        }
        if (!$.isNumeric($('#back-pressure-object-threshold').val())) {
            errors.push('Back pressure object threshold must be an integer value');
        }
        if (nfCommon.isBlank($('#back-pressure-data-size-threshold').val())) {
            errors.push('Back pressure data size threshold must be specified');
        }
        if ($('#load-balance-strategy-combo').combo('getSelectedOption').value === 'PARTITION_BY_ATTRIBUTE'
            && nfCommon.isBlank($('#load-balance-partition-attribute').val())) {
            errors.push('Cannot set Load Balance Strategy to "Partition by attribute" without providing a partitioning "Attribute Name"');
        }

        if (errors.length > 0) {
            nfDialog.showOkDialog({
                headerText: 'Configuration Error',
                dialogContent: nfCommon.formatUnorderedList(errors)
            });
            return false;
        } else {
            return true;
        }
    };

    /**
     * Resets the dialog.
     */
    var resetDialog = function () {
        // reset the prioritizers
        var selectedList = $('#prioritizer-selected');
        var availableList = $('#prioritizer-available');
        selectedList.children().detach().appendTo(availableList);

        // sort the available list
        var listItems = availableList.children('li').get();
        listItems.sort(function (a, b) {
            var compA = $(a).text().toUpperCase();
            var compB = $(b).text().toUpperCase();
            return (compA < compB) ? -1 : (compA > compB) ? 1 : 0;
        });

        // clear the available list and re-insert each list item
        $.each(listItems, function () {
            $(this).detach();
        });
        $.each(listItems, function () {
            $(this).appendTo(availableList);
        });

        // reset the fields
        $('#connection-name').val('');
        $('#relationship-names').css('border-width', '0').empty();
        $('#relationship-names-container').hide();

        // clear the id field
        nfCommon.clearField('connection-id');

        // hide all the connection source panels
        $('#processor-source').hide();
        $('#input-port-source').hide();
        $('#output-port-source').hide();
        $('#read-only-output-port-source').hide();
        $('#funnel-source').hide();

        // hide all the connection destination panels
        $('#processor-destination').hide();
        $('#input-port-destination').hide();
        $('#output-port-destination').hide();
        $('#funnel-destination').hide();

        // clear and destination details
        $('#connection-source-id').val('');
        $('#connection-source-component-id').val('');
        $('#connection-source-group-id').val('');

        // clear any destination details
        $('#connection-destination-id').val('');
        $('#connection-destination-component-id').val('');
        $('#connection-destination-group-id').val('');

        // clear any ports
        $('#output-port-options').empty();
        $('#input-port-options').empty();

        // clear load balance settings
        $('#load-balance-strategy-combo').combo('setSelectedOption', nfCommon.loadBalanceStrategyOptions[0]);
        $('#load-balance-partition-attribute').val('');
        $('#load-balance-compression-combo').combo('setSelectedOption', nfCommon.loadBalanceCompressionOptions[0]);

        // see if the temp edge needs to be removed
        removeTempEdge();
    };

    var nfConnectionConfiguration = {

        /**
         * Initialize the connection configuration.
         *
         * @param nfBirdseyeRef   The nfBirdseye module.
         * @param nfGraphRef   The nfGraph module.
         */
        init: function (nfBirdseyeRef, nfGraphRef, defaultBackPressureObjectThresholdRef, defaultBackPressureDataSizeThresholdRef) {
            nfBirdseye = nfBirdseyeRef;
            nfGraph = nfGraphRef;

            defaultBackPressureObjectThreshold = defaultBackPressureObjectThresholdRef;
            defaultBackPressureDataSizeThreshold = defaultBackPressureDataSizeThresholdRef;

            // initially hide the relationship names container
            $('#relationship-names-container').hide();

            // initialize the configure connection dialog
            $('#connection-configuration').modal({
                scrollableContentStyle: 'scrollable',
                headerText: 'Configure Connection',
                handler: {
                    close: function () {
                        // reset the dialog on close
                        resetDialog();
                    },
                    open: function () {
                        nfCommon.toggleScrollable($('#' + this.find('.tab-container').attr('id') + '-content').get(0));
                    }
                }
            });

            // initialize the properties tabs
            $('#connection-configuration-tabs').tabbs({
                tabStyle: 'tab',
                selectedTabStyle: 'selected-tab',
                scrollableTabContentStyle: 'scrollable',
                tabs: [{
                    name: 'Details',
                    tabContentId: 'connection-details-tab-content'
                }, {
                    name: 'Settings',
                    tabContentId: 'connection-settings-tab-content'
                }]
            });

            // initialize the load balance strategy combo
            $('#load-balance-strategy-combo').combo({
                options: nfCommon.loadBalanceStrategyOptions,
                select: function (selectedOption) {
                    // Show the appropriate configurations
                    if (selectedOption.value === 'PARTITION_BY_ATTRIBUTE') {
                        $('#load-balance-partition-attribute-setting-separator').show();
                        $('#load-balance-partition-attribute-setting').show();
                    } else {
                        $('#load-balance-partition-attribute-setting-separator').hide();
                        $('#load-balance-partition-attribute-setting').hide();
                    }
                    if (selectedOption.value === 'DO_NOT_LOAD_BALANCE') {
                        $('#load-balance-compression-setting').hide();
                    } else {
                        $('#load-balance-compression-setting').show();
                    }
                }
            });


            // initialize the load balance compression combo
            $('#load-balance-compression-combo').combo({
                options: nfCommon.loadBalanceCompressionOptions
            });

            // load the processor prioritizers
            $.ajax({
                type: 'GET',
                url: config.urls.prioritizers,
                dataType: 'json'
            }).done(function (response) {
                // create an element for each available prioritizer
                $.each(response.prioritizerTypes, function (i, documentedType) {
                    nfConnectionConfiguration.addAvailablePrioritizer('#prioritizer-available', documentedType);
                });

                // make the prioritizer containers sortable
                $('#prioritizer-available, #prioritizer-selected').sortable({
                    containment: $('#connection-settings-tab-content').find('.settings-right'),
                    connectWith: 'ul',
                    placeholder: 'ui-state-highlight',
                    scroll: true,
                    opacity: 0.6
                });
                $('#prioritizer-available, #prioritizer-selected').disableSelection();
            }).fail(nfErrorHandler.handleAjaxError);
        },

        /**
         * Adds the specified prioritizer to the specified container.
         *
         * @argument {string} prioritizerContainer      The dom Id of the prioritizer container
         * @argument {object} prioritizerType           The type of prioritizer
         */
        addAvailablePrioritizer: function (prioritizerContainer, prioritizerType) {
            var type = prioritizerType.type;
            var name = nfCommon.substringAfterLast(type, '.');

            // add the prioritizers to the available list
            var prioritizerList = $(prioritizerContainer);
            var prioritizer = $('<li></li>').append($('<span style="float: left;"></span>').text(name)).attr('id', type).addClass('ui-state-default').appendTo(prioritizerList);

            // add the description if applicable
            if (nfCommon.isDefinedAndNotNull(prioritizerType.description)) {
                $('<div class="fa fa-question-circle"></div>').appendTo(prioritizer).qtip($.extend({
                    content: nfCommon.escapeHtml(prioritizerType.description)
                }, nfCommon.config.tooltipConfig));
            }
        },

        /**
         * Shows the dialog for creating a new connection.
         *
         * @argument {string} sourceId      The source id
         * @argument {string} destinationId The destination id
         */
        createConnection: function (sourceId, destinationId) {
            // select the source and destination
            var source = d3.select('#id-' + sourceId);
            var destination = d3.select('#id-' + destinationId);

            if (source.empty() || destination.empty()) {
                return;
            }

            // reset labels
            $('#connection-source-group div.setting-name').text('Within Group')
            $('#connection-destination-group div.setting-name').text('Within Group')
            $('#connection-remote-source-url').hide();
            $('#connection-remote-destination-url').hide();

            // initialize the connection dialog
            $.when(initializeSourceNewConnectionDialog(source), initializeDestinationNewConnectionDialog(destination)).done(function () {
                // set the default values
                $('#flow-file-expiration').val('0 sec');
                $('#back-pressure-object-threshold').val(defaultBackPressureObjectThreshold);
                $('#back-pressure-data-size-threshold').val(defaultBackPressureDataSizeThreshold);

                // select the first tab
                $('#connection-configuration-tabs').find('li:first').click();

                // configure the header and show the dialog
                $('#connection-configuration').modal('setHeaderText', 'Create Connection').modal('show');

                // add the ellipsis if necessary
                $('#connection-configuration div.relationship-name').ellipsis();

                // fill in the connection id
                nfCommon.populateField('connection-id', null);

                // show the border if necessary
                var relationshipNames = $('#relationship-names');
                if (relationshipNames.is(':visible') && relationshipNames.get(0).scrollHeight > Math.round(relationshipNames.innerHeight())) {
                    relationshipNames.css('border-width', '1px');
                }
            }).fail(function () {
                // see if the temp edge needs to be removed
                removeTempEdge();
            });
        },

        /**
         * Shows the configuration for the specified connection. If a destination is
         * specified it will be considered a new destination.
         *
         * @argument {selection} selection         The connection entry
         * @argument {selection} destination          Optional new destination
         */
        showConfiguration: function (selection, destination) {
            return $.Deferred(function (deferred) {
                var connectionEntry = selection.datum();
                var connection = connectionEntry.component;

                // identify the source component
                var sourceComponentId = nfCanvasUtils.getConnectionSourceComponentId(connectionEntry);
                var source = d3.select('#id-' + sourceComponentId);

                // identify the destination component
                if (nfCommon.isUndefinedOrNull(destination)) {
                    var destinationComponentId = nfCanvasUtils.getConnectionDestinationComponentId(connectionEntry);
                    destination = d3.select('#id-' + destinationComponentId);
                }

                // reset labels
                $('#connection-source-group div.setting-name').text('Within Group')
                $('#connection-destination-group div.setting-name').text('Within Group')
                $('#connection-remote-source-url').hide();
                $('#connection-remote-destination-url').hide();

                // initialize the connection dialog
                $.when(initializeSourceEditConnectionDialog(source), initializeDestinationEditConnectionDialog(destination, connection.destination)).done(function () {
                    var availableRelationships = connection.availableRelationships;
                    var selectedRelationships = connection.selectedRelationships;

                    // show the available relationship if applicable
                    if (nfCommon.isDefinedAndNotNull(availableRelationships) || nfCommon.isDefinedAndNotNull(selectedRelationships)) {
                        // populate the available connections
                        $.each(availableRelationships, function (i, name) {
                            createRelationshipOption(name);
                        });

                        addDialogRelationshipsChangeListener();

                        // ensure all selected relationships are present
                        // (may be undefined) and selected
                        $.each(selectedRelationships, function (i, name) {
                            // mark undefined relationships accordingly
                            if ($.inArray(name, availableRelationships) === -1) {
                                var option = createRelationshipOption(name);
                                $(option).children('div.relationship-name').addClass('undefined');
                            }

                            // ensure all selected relationships are checked
                            var relationships = $('#relationship-names').children('div');
                            $.each(relationships, function (i, relationship) {
                                var relationshipName = $(relationship).children('span.relationship-name-value');
                                if (relationshipName.text() === name) {
                                    $(relationship).children('div.available-relationship').removeClass('checkbox-unchecked').addClass('checkbox-checked');
                                }
                            });
                        });
                    }

                    // if the source is a process group or remote process group, select the appropriate port if applicable
                    if (nfCanvasUtils.isProcessGroup(source) || nfCanvasUtils.isRemoteProcessGroup(source)) {
                        // populate the connection source details
                        $('#connection-source-id').val(connection.source.id);
                        $('#read-only-output-port-name').text(connection.source.name).attr('title', connection.source.name);
                    }

                    // if the destination is a process gorup or remote process group, select the appropriate port if applicable
                    if (nfCanvasUtils.isProcessGroup(destination) || nfCanvasUtils.isRemoteProcessGroup(destination)) {
                        var destinationData = destination.datum();

                        // when the group ids differ, its a new destination component so we don't want to preselect any port
                        if (connection.destination.groupId === destinationData.id) {
                            $('#input-port-options').combo('setSelectedOption', {
                                value: connection.destination.id
                            });
                        }
                    }

                    // set the connection settings
                    $('#connection-name').val(connection.name);
                    $('#flow-file-expiration').val(connection.flowFileExpiration);
                    $('#back-pressure-object-threshold').val(connection.backPressureObjectThreshold);
                    $('#back-pressure-data-size-threshold').val(connection.backPressureDataSizeThreshold);

                    // select the load balance combos
                    $('#load-balance-strategy-combo').combo('setSelectedOption', {
                        value: connection.loadBalanceStrategy
                    });
                    $('#load-balance-compression-combo').combo('setSelectedOption', {
                        value: connection.loadBalanceCompression
                    });
                    $('#load-balance-partition-attribute').val(connection.loadBalancePartitionAttribute);

                    // format the connection id
                    nfCommon.populateField('connection-id', connection.id);

                    // handle each prioritizer
                    $.each(connection.prioritizers, function (i, type) {
                        $('#prioritizer-available').children('li[id="' + type + '"]').detach().appendTo('#prioritizer-selected');
                    });

                    // store the connection details
                    $('#connection-uri').val(connectionEntry.uri);

                    // configure the button model
                    $('#connection-configuration').modal('setButtonModel', [{
                        buttonText: 'Apply',
                        color: {
                            base: '#728E9B',
                            hover: '#004849',
                            text: '#ffffff'
                        },
                        disabled: function () {
                            // ensure some relationships were selected with a processor as the source
                            if (nfCanvasUtils.isProcessor(source)) {
                                return getSelectedRelationships().length === 0 || isConnectionUpsertionInProgess();
                            }
                            return isConnectionUpsertionInProgess();
                        },
                        handler: {
                            click: function () {
                                setConnectionUpsertionInProgess(true);
                                // see if we're working with a processor as the source
                                if (nfCanvasUtils.isProcessor(source)) {
                                    // update the selected relationships
                                    updateConnection(getSelectedRelationships()).done(function () {
                                        deferred.resolve();
                                    }).fail(function () {
                                        deferred.reject();
                                    }).always(function(){
                                        setConnectionUpsertionInProgess(false);
                                    });
                                } else {
                                    // there are no relationships, but the source wasn't a processor, so update anyway
                                    updateConnection(undefined).done(function () {
                                        deferred.resolve();
                                    }).fail(function () {
                                        deferred.reject();
                                    }).always(function(){
                                        setConnectionUpsertionInProgess(false);
                                    });
                                }
                            }
                        }
                    },
                        {
                            buttonText: 'Cancel',
                            color: {
                                base: '#E3E8EB',
                                hover: '#C7D2D7',
                                text: '#004849'
                            },
                            disabled: function(){
                                return isConnectionUpsertionInProgess();
                            },
                            handler: {
                                click: function () {
                                    // hide the dialog
                                    $('#connection-configuration').modal('hide');

                                    // reject the deferred
                                    deferred.reject();
                                }
                            }
                        }]);

                    // show the details dialog
                    $('#connection-configuration').modal('setHeaderText', 'Configure Connection').modal('show');

                    // add the ellipsis if necessary
                    $('#connection-configuration div.relationship-name').ellipsis();

                    // show the border if necessary
                    var relationshipNames = $('#relationship-names');
                    if (relationshipNames.is(':visible') && relationshipNames.get(0).scrollHeight > Math.round(relationshipNames.innerHeight())) {
                        relationshipNames.css('border-width', '1px');
                    }
                }).fail(function () {
                    deferred.reject();
                });
            }).promise();
        }
    };

    return nfConnectionConfiguration;
}));