/*
 * 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) {
            nfBirdseye = nfBirdseyeRef;
            nfGraph = nfGraphRef;

            // 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, defaultSettings) {
            // 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(defaultSettings.flowfileExpiration);
                $('#back-pressure-object-threshold').val(defaultSettings.objectThreshold);
                $('#back-pressure-data-size-threshold').val(defaultSettings.dataSizeThreshold);

                // 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;
}));
