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

/**
 * Lists FlowFiles from a given connection.
 */
(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        define(['jquery',
                'Slick',
                'nf.Common',
                'nf.Dialog',
                'nf.Shell',
                'nf.ng.Bridge',
                'nf.ClusterSummary',
                'nf.ErrorHandler',
                'nf.Storage',
                'nf.CanvasUtils'],
            function ($, Slick, nfCommon, nfDialog, nfShell, nfNgBridge, nfClusterSummary, nfErrorHandler, nfStorage, nfCanvasUtils) {
                return (nf.QueueListing = factory($, Slick, nfCommon, nfDialog, nfShell, nfNgBridge, nfClusterSummary, nfErrorHandler, nfStorage, nfCanvasUtils));
            });
    } else if (typeof exports === 'object' && typeof module === 'object') {
        module.exports = (nf.QueueListing =
            factory(require('jquery'),
                require('Slick'),
                require('nf.Common'),
                require('nf.Dialog'),
                require('nf.Shell'),
                require('nf.ng.Bridge'),
                require('nf.ClusterSummary'),
                require('nf.ErrorHandler'),
                require('nf.Storage'),
                require('nf.CanvasUtils')));
    } else {
        nf.QueueListing = factory(root.$,
            root.Slick,
            root.nf.Common,
            root.nf.Dialog,
            root.nf.Shell,
            root.nf.ng.Bridge,
            root.nf.ClusterSummary,
            root.nf.ErrorHandler,
            root.nf.Storage,
            root.nf.CanvasUtils);
    }
}(this, function ($, Slick, nfCommon, nfDialog, nfShell, nfNgBridge, nfClusterSummary, nfErrorHandler, nfStorage, nfCanvasUtils) {
    'use strict';

    /**
     * Configuration object used to hold a number of configuration items.
     */
    var config = {
        urls: {
        }
    };

    /**
     * Initializes the listing request status dialog.
     */
    var initializeListingRequestStatusDialog = function () {
        // configure the drop request status dialog
        $('#listing-request-status-dialog').modal({
            scrollableContentStyle: 'scrollable',
            headerText: 'Queue Listing',
            handler: {
                close: function () {
                    // clear the current button model
                    $('#listing-request-status-dialog').modal('setButtonModel', []);
                }
            }
        });
    };

    /**
     * Initializes the listing column model.
     */
    var getListingColumnModel = function () {
        // define a custom formatter for showing more processor details
        var moreDetailsFormatter = function (row, cell, value, columnDef, dataContext) {
            return '<div class="pointer show-flowfile-details fa fa-info-circle" title="View Details" style="float: left;"></div>';
        };

        // function for formatting data sizes
        var dataSizeFormatter = function (row, cell, value, columnDef, dataContext) {
            return nfCommon.formatDataSize(value);
        };

        // function for formatting durations
        var durationFormatter = function (row, cell, value, columnDef, dataContext) {
            return nfCommon.formatDuration(value);
        };

        // function for formatting penalization
        var penalizedFormatter = function (row, cell, value, columnDef, dataContext) {
            if(value == 0) {
                return 'No';
            }

            return nfCommon.formatDuration(value);
        };

        // initialize the queue listing table
        var queueListingColumns = [
            {
                id: 'moreDetails',
                field: 'moreDetails',
                name: '&nbsp;',
                sortable: false,
                resizable: false,
                formatter: moreDetailsFormatter,
                width: 50,
                maxWidth: 50
            },
            {
                id: 'position',
                name: 'Position',
                field: 'position',
                sortable: false,
                resizable: false,
                width: 75,
                maxWidth: 75,
                formatter: nfCommon.genericValueFormatter
            },
            {
                id: 'uuid',
                name: 'UUID',
                field: 'uuid',
                sortable: false,
                resizable: true,
                formatter: nfCommon.genericValueFormatter
            },
            {
                id: 'filename',
                name: 'Filename',
                field: 'filename',
                sortable: false,
                resizable: true,
                formatter: nfCommon.genericValueFormatter
            },
            {
                id: 'size',
                name: 'File Size',
                field: 'size',
                sortable: false,
                resizable: true,
                defaultSortAsc: false,
                formatter: dataSizeFormatter
            },
            {
                id: 'queuedDuration',
                name: 'Queued Duration',
                field: 'queuedDuration',
                sortable: false,
                resizable: true,
                formatter: durationFormatter
            },
            {
                id: 'lineageDuration',
                name: 'Lineage Duration',
                field: 'lineageDuration',
                sortable: false,
                resizable: true,
                formatter: durationFormatter
            },
            {
                id: 'penalized',
                name: 'Penalized',
                field: 'penaltyExpiresIn',
                sortable: false,
                resizable: false,
                width: 100,
                maxWidth: 100,
                formatter: penalizedFormatter
            }
        ];

        // conditionally show the cluster node identifier
        if (nfClusterSummary.isConnectedToCluster()) {
            queueListingColumns.push({
                id: 'clusterNodeAddress',
                name: 'Node',
                field: 'clusterNodeAddress',
                sortable: false,
                resizable: true,
                formatter: nfCommon.genericValueFormatter
            });
        }

        // function for formatting actions column
        var actionsFormatter = function (row,cell,value,columnDef,dataContext) {
            var formatted = '';

            var disabled = (dataContext.size > 0)?false:true;
            formatted += '<div class="icon download-flowfile-content fa fa-download '+((disabled)?'disabled':'pointer')+'"'+
                ' title="'+((disabled)?'No content available to download':'Download content')+'" aria-hidden="true"></div>';

            if(nfCommon.isContentViewConfigured()){
                formatted += '<div class="icon view-flowfile-content fa fa-eye '+((disabled)?'disabled':'pointer')+'"'+
                    ' title="'+((disabled)?'No content available to view':'View content')+'" aria-hidden="true"></div>';
            }

            if(nfCommon.canAccessProvenance()){
                formatted += '<div title="Provenance" class="pointer icon icon-provenance view-provenance" aria-hidden="true"></div>';
            }

            return formatted;
        };

        // add an actions column to the column model
        queueListingColumns.push({
            id: 'actions',
            name: '&nbsp;',
            resizable: false,
            formatter: actionsFormatter,
            sortable: false,
            width: 75,
            maxWidth: 75
        });


        return queueListingColumns;
    };

    /**
     * Downloads the content for the flowfile currently being viewed.
     *
     * @param flowFileSummary|{flowfile} (optional) -  the flowfile summary
     */
    var downloadContent = function (flowFileSummary) {
        var dataUri = ((nfCommon.isDefinedAndNotNull(flowFileSummary.uri))?flowFileSummary.uri:$('#flowfile-uri').text())+ '/content';

        var parameters = {};

        // conditionally include the cluster node id
        var clusterNodeId = (nfCommon.isDefinedAndNotNull(flowFileSummary.clusterNodeId))?flowFileSummary.clusterNodeId:$('#flowfile-cluster-node-id').text();
        if (!nfCommon.isBlank(clusterNodeId)) {
            parameters['clusterNodeId'] = clusterNodeId;
        }

        // open the url
        if ($.isEmptyObject(parameters)) {
            window.open(dataUri);
        } else {
            window.open(dataUri + '?' + $.param(parameters));
        }
    };

    /**
     * Views the content for the flowfile currently being viewed.
     *
     * @param flowFileSummary|{flowfile} (optional) -  the flowfile summary
     */
    var viewContent = function (flowFileSummary) {

        var dataUri = ((nfCommon.isDefinedAndNotNull(flowFileSummary.uri))?flowFileSummary.uri:$('#flowfile-uri').text())+ '/content';

        var dataUriParameters = {};

        // conditionally include the cluster node id
        var clusterNodeId = (nfCommon.isDefinedAndNotNull(flowFileSummary.clusterNodeId))?flowFileSummary.clusterNodeId:$('#flowfile-cluster-node-id').text();
        if (!nfCommon.isBlank(clusterNodeId)) {
            dataUriParameters['clusterNodeId'] = clusterNodeId;
        }

        // include parameters if necessary
        if ($.isEmptyObject(dataUriParameters) === false) {
            dataUri = dataUri + '?' + $.param(dataUriParameters);
        }

        // open the content viewer
        var contentViewerUrl = $('#nifi-content-viewer-url').text();

        // if there's already a query string don't add another ?... this assumes valid
        // input meaning that if the url has already included a ? it also contains at
        // least one query parameter
        if (contentViewerUrl.indexOf('?') === -1) {
            contentViewerUrl += '?';
        } else {
            contentViewerUrl += '&';
        }

        var contentViewerParameters = {
            'ref': dataUri
        };

        // open the content viewer
        window.open(contentViewerUrl + $.param(contentViewerParameters));
    };

    /**
     * Performs a listing on the specified connection.
     *
     * @param connection the connection
     */
    var performListing = function (connection) {
        var MAX_DELAY = 4;
        var cancelled = false;
        var listingRequest = null;
        var listingRequestTimer = null;

        return $.Deferred(function (deferred) {
            // updates the progress bar
            var updateProgress = function (percentComplete) {
                // remove existing labels
                var progressBar = $('#listing-request-percent-complete');
                progressBar.find('div.progress-label').remove();
                progressBar.find('md-progress-linear').remove();

                // update the progress
                var label = $('<div class="progress-label"></div>').text(percentComplete + '%');
                (nfNgBridge.injector.get('$compile')($('<md-progress-linear ng-cloak ng-value="' + percentComplete + '" class="md-hue-2" md-mode="determinate" aria-label="Searching Queue"></md-progress-linear>'))(nfNgBridge.rootScope)).appendTo(progressBar);
                progressBar.append(label);
            };

            // update the button model of the drop request status dialog
            $('#listing-request-status-dialog').modal('setButtonModel', [{
                headerText: 'Queue Listing',
                buttonText: 'Stop',
                color: {
                    base: '#728E9B',
                    hover: '#004849',
                    text: '#ffffff'
                },
                handler: {
                    click: function () {
                        cancelled = true;

                        // we are waiting for the next poll attempt
                        if (listingRequestTimer !== null) {
                            // cancel it
                            clearTimeout(listingRequestTimer);

                            // cancel the listing request
                            completeListingRequest();
                        }
                    }
                }
            }]);

            // completes the listing request by removing it
            var completeListingRequest = function () {
                $('#listing-request-status-dialog').modal('hide');

                var reject = cancelled;

                // ensure the listing requests are present
                if (nfCommon.isDefinedAndNotNull(listingRequest)) {
                    $.ajax({
                        type: 'DELETE',
                        url: listingRequest.uri,
                        dataType: 'json'
                    });

                    // use the listing request from when the listing completed
                    if (nfCommon.isEmpty(listingRequest.flowFileSummaries)) {
                        if (cancelled === false) {
                            reject = true;

                            // show the dialog
                            nfDialog.showOkDialog({
                                headerText: 'Queue Listing',
                                dialogContent: 'The queue has no FlowFiles.'
                            });
                        }
                    } else {
                        // update the queue size
                        $('#total-flowfiles-count').text(nfCommon.formatInteger(listingRequest.queueSize.objectCount));
                        $('#total-flowfiles-size').text(nfCommon.formatDataSize(listingRequest.queueSize.byteCount));

                        // update the last updated time
                        $('#queue-listing-last-refreshed').text(listingRequest.lastUpdated);

                        // show a message for the queue listing if necessary
                        var queueListingTable = $('#queue-listing-table');
                        var queueListingMessage = $('#queue-listing-message');
                        if (listingRequest.sourceRunning === true || listingRequest.destinationRunning === true) {
                            if (listingRequest.souceRunning === true && listingRequest.destinationRunning === true) {
                                queueListingMessage.text('The source and destination of this queue are currently running. This listing may no longer be accurate.').show();
                            } else if (listingRequest.sourceRunning === true) {
                                queueListingMessage.text('The source of this queue is currently running. This listing may no longer be accurate.').show();
                            } else if (listingRequest.destinationRunning === true) {
                                queueListingMessage.text('The destination of this queue is currently running. This listing may no longer be accurate.').show();
                            }
                        } else {
                            queueListingMessage.text('').hide();
                        }

                        // get the grid to load the data
                        var queueListingGrid = $('#queue-listing-table').data('gridInstance');
                        queueListingGrid.setColumns(getListingColumnModel());
                        var queueListingData = queueListingGrid.getData();

                        // load the flowfiles
                        queueListingData.beginUpdate();
                        queueListingData.setItems(listingRequest.flowFileSummaries, 'uuid');
                        queueListingData.endUpdate();
                    }
                } else {
                    reject = true;
                }

                if (reject) {
                    deferred.reject();
                } else {
                    deferred.resolve();
                }
            };

            // process the listing request
            var processListingRequest = function (delay) {
                // update the percent complete
                updateProgress(listingRequest.percentCompleted);

                // update the status of the listing request
                $('#listing-request-status-message').text(listingRequest.state);

                // close the dialog if the
                if (listingRequest.finished === true || cancelled === true) {
                    completeListingRequest();
                } else {
                    // wait delay to poll again
                    listingRequestTimer = setTimeout(function () {
                        // clear the listing request timer
                        listingRequestTimer = null;

                        // schedule to poll the status again in nextDelay
                        pollListingRequest(Math.min(MAX_DELAY, delay * 2));
                    }, delay * 1000);
                }
            };

            // schedule for the next poll iteration
            var pollListingRequest = function (nextDelay) {
                $.ajax({
                    type: 'GET',
                    url: listingRequest.uri,
                    dataType: 'json'
                }).done(function (response) {
                    listingRequest = response.listingRequest;
                    processListingRequest(nextDelay);
                }).fail(completeListingRequest).fail(nfErrorHandler.handleAjaxError);
            };

            // issue the request to list the flow files
            $.ajax({
                type: 'POST',
                url: '../nifi-api/flowfile-queues/' + connection.id + '/listing-requests',
                dataType: 'json',
                contentType: 'application/json'
            }).done(function (response) {
                // initialize the progress bar value
                updateProgress(0);

                // show the progress dialog
                $('#listing-request-status-dialog').modal('show');

                // process the drop request
                listingRequest = response.listingRequest;
                processListingRequest(1);
            }).fail(completeListingRequest).fail(nfErrorHandler.handleAjaxError);
        }).promise();
    };

    /**
     * Shows the details for the specified flowfile.
     *
     * @param flowFileSummary the flowfile summary
     */
    var showFlowFileDetails = function (flowFileSummary) {
        // formats an flowfile detail
        var formatFlowFileDetail = function (label, value) {
            $('<div class="flowfile-detail"></div>').append(
                $('<div class="detail-name"></div>').text(label)).append(
                $('<div class="detail-value">' + nfCommon.formatValue(value) + '</div>').ellipsis()).append(
                $('<div class="clear"></div>')).appendTo('#additional-flowfile-details');
        };

        // formats the content value
        var formatContentValue = function (element, value) {
            if (nfCommon.isDefinedAndNotNull(value)) {
                element.removeClass('unset').text(value);
            } else {
                element.addClass('unset').text('No value set');
            }
        };

        var params = {};
        if (nfCommon.isDefinedAndNotNull(flowFileSummary.clusterNodeId)) {
            params['clusterNodeId'] = flowFileSummary.clusterNodeId;
        }

        $.ajax({
            type: 'GET',
            url: flowFileSummary.uri,
            data: params,
            dataType: 'json'
        }).done(function (response) {
            var flowFile = response.flowFile;

            // set a default for flowfiles with no content claim
            var fileSize = nfCommon.isDefinedAndNotNull(flowFile.contentClaimFileSize) ? flowFile.contentClaimFileSize : nfCommon.formatDataSize(0);

            // show the URI to this flowfile
            $('#flowfile-uri').text(flowFile.uri);

            // show the flowfile details dialog
            $('#flowfile-uuid').html(nfCommon.formatValue(flowFile.uuid));
            $('#flowfile-filename').html(nfCommon.formatValue(flowFile.filename));
            $('#flowfile-queue-position').html(nfCommon.formatValue(flowFile.position));
            $('#flowfile-file-size').html(nfCommon.formatValue(fileSize));
            $('#flowfile-queued-duration').text(nfCommon.formatDuration(flowFile.queuedDuration));
            $('#flowfile-lineage-duration').text(nfCommon.formatDuration(flowFile.lineageDuration));
            $('#flowfile-penalized').text(flowFile.penaltyExpiresIn == 0 ? 'No' : nfCommon.formatDuration(flowFile.penaltyExpiresIn));

            // conditionally show the cluster node identifier
            if (nfCommon.isDefinedAndNotNull(flowFileSummary.clusterNodeId)) {
                // save the cluster node id
                $('#flowfile-cluster-node-id').text(flowFileSummary.clusterNodeId);

                // render the cluster node address
                formatFlowFileDetail('Node Address', flowFileSummary.clusterNodeAddress);
            }

            if (nfCommon.isDefinedAndNotNull(flowFile.contentClaimContainer)) {
                // content claim
                formatContentValue($('#content-container'), flowFile.contentClaimContainer);
                formatContentValue($('#content-section'), flowFile.contentClaimSection);
                formatContentValue($('#content-identifier'), flowFile.contentClaimIdentifier);
                formatContentValue($('#content-offset'), flowFile.contentClaimOffset);
                formatContentValue($('#content-bytes'), flowFile.contentClaimFileSizeBytes);

                // input content file size
                var contentSize = $('#content-size');
                formatContentValue(contentSize, flowFile.contentClaimFileSize);
                if (nfCommon.isDefinedAndNotNull(flowFile.contentClaimFileSize)) {
                    // over the default tooltip with the actual byte count
                    contentSize.attr('title', nfCommon.formatInteger(flowFile.contentClaimFileSizeBytes) + ' bytes');
                }

                // show the content details
                $('#flowfile-content-details').show();
                $('#flowfile-with-no-content').hide();
            } else {
                $('#flowfile-content-details').hide();
                $('#flowfile-with-no-content').show();
            }

            // attributes
            var attributesContainer = $('#flowfile-attributes-container');

            // get any action details
            var sortedAttributeNames = Object.keys(flowFile.attributes).sort();
            sortedAttributeNames.forEach(function (attributeName) {
                var attributeValue = flowFile.attributes[attributeName];

                // create the attribute record
                var attributeRecord = $('<div class="attribute-detail"></div>')
                    .append($('<div class="attribute-name">' + nfCommon.formatValue(attributeName) + '</div>').ellipsis())
                    .appendTo(attributesContainer);

                // add the current value
                attributeRecord
                    .append($('<div class="attribute-value">' + nfCommon.formatValue(attributeValue) + '</div>').ellipsis())
                    .append('<div class="clear"></div>');
            });

            // show the dialog
            $('#flowfile-details-dialog').modal('show');
        }).fail(nfErrorHandler.handleAjaxError);
    };

    var nfQueueListing = {
        init: function () {
            initializeListingRequestStatusDialog();

            // define mouse over event for the refresh button
            $('#queue-listing-refresh-button').click(function () {
                var connection = $('#queue-listing-table').data('connection');
                performListing(connection);
            });

            var queueListingOptions = {
                forceFitColumns: true,
                enableTextSelectionOnCells: true,
                enableCellNavigation: false,
                enableColumnReorder: false,
                autoEdit: false,
                rowHeight: 24
            };

            // initialize the dataview
            var queueListingData = new Slick.Data.DataView({
                inlineFilters: false
            });
            queueListingData.setItems([]);

            // initialize the grid
            var queueListingGrid = new Slick.Grid('#queue-listing-table', queueListingData, getListingColumnModel(), queueListingOptions);
            queueListingGrid.setSelectionModel(new Slick.RowSelectionModel());
            queueListingGrid.registerPlugin(new Slick.AutoTooltips());

            // configure a click listener
            queueListingGrid.onClick.subscribe(function (e, args) {
                var target = $(e.target);

                // get the node at this row
                var item = queueListingData.getItem(args.row);

                // determine the desired action
                if (queueListingGrid.getColumns()[args.cell].id === 'moreDetails') {
                    if (target.hasClass('show-flowfile-details')) {
                        showFlowFileDetails(item);
                    }
                } else if (queueListingGrid.getColumns()[args.cell].id === 'actions') {
                    if (target.hasClass('view-provenance')) {
                        // close the settings dialog
                        $('#shell-close-button').click();

                        // open the provenance page with the specified component
                        nfShell.showPage('provenance?' + $.param({
                                flowFileUuid: item.uuid
                            }));
                    } else if (target.hasClass('download-flowfile-content') && !target.hasClass('disabled')) {
                        downloadContent(item);
                    } else if (target.hasClass('view-flowfile-content') && !target.hasClass('disabled')) {
                        viewContent(item);
                    }
                }
            });

            // wire up the dataview to the grid
            queueListingData.onRowCountChanged.subscribe(function (e, args) {
                queueListingGrid.updateRowCount();
                queueListingGrid.render();

                // update the total number of displayed flowfiles
                $('#displayed-flowfiles').text(args.current);
            });
            queueListingData.onRowsChanged.subscribe(function (e, args) {
                queueListingGrid.invalidateRows(args.rows);
                queueListingGrid.render();
            });

            // hold onto an instance of the grid
            $('#queue-listing-table').data('gridInstance', queueListingGrid);

            // initialize the number of display items
            $('#displayed-flowfiles').text('0');
        },

        /**
         * Initializes the flowfile details dialog.
         */
        initFlowFileDetailsDialog: function () {
            $('#content-download').on('click', downloadContent);

            // only show if content viewer is configured
            if (nfCommon.isContentViewConfigured()) {
                $('#content-view').show();
                $('#content-view').on('click', viewContent);
            }

            $('#flowfile-details-tabs').tabbs({
                tabStyle: 'tab',
                selectedTabStyle: 'selected-tab',
                scrollableTabContentStyle: 'scrollable',
                tabs: [{
                    name: 'Details',
                    tabContentId: 'flowfile-details-tab-content'
                }, {
                    name: 'Attributes',
                    tabContentId: 'flowfile-attributes-tab-content'
                }]
            });

            $('#flowfile-details-dialog').modal({
                scrollableContentStyle: 'scrollable',
                headerText: 'FlowFile',
                buttons: [{
                    buttonText: 'Ok',
                    color: {
                        base: '#728E9B',
                        hover: '#004849',
                        text: '#ffffff'
                    },
                    handler: {
                        click: function () {
                            $('#flowfile-details-dialog').modal('hide');
                        }
                    }
                }],
                handler: {
                    close: function () {
                        // clear the details
                        $('#flowfile-attributes-container').empty();
                        $('#flowfile-cluster-node-id').text('');
                        $('#additional-flowfile-details').empty();
                    },
                    open: function () {
                        nfCommon.toggleScrollable($('#' + this.find('.tab-container').attr('id') + '-content').get(0));
                    }
                }
            });
        },

        /**
         * Update the size of the grid based on its container's current size.
         */
        resetTableSize: function () {
            var queueListingGrid = $('#queue-listing-table').data('gridInstance');
            if (nfCommon.isDefinedAndNotNull(queueListingGrid)) {
                queueListingGrid.resizeCanvas();
            }
        },

        /**
         * Shows the listing of the FlowFiles from a given connection.
         *
         * @param   {object}    The connection
         */
        listQueue: function (connection) {
            // perform the initial listing
            performListing(connection).done(function () {
                // update the connection name
                var connectionName = '';
                if (connection.permissions.canRead) {
                    connectionName = nfCanvasUtils.formatConnectionName(connection.component);
                }
                if (connectionName === '') {
                    connectionName = 'Connection';
                }
                $('#queue-listing-header-text').text(connectionName);

                // show the listing container
                nfShell.showContent('#queue-listing-container').done(function () {
                    $('#queue-listing-table').removeData('connection');

                    // clear the table
                    var queueListingGrid = $('#queue-listing-table').data('gridInstance');
                    var queueListingData = queueListingGrid.getData();

                    // clear the flowfiles
                    queueListingData.beginUpdate();
                    queueListingData.setItems([], 'uuid');
                    queueListingData.endUpdate();

                    // reset stats
                    $('#displayed-flowfiles, #total-flowfiles-count').text('0');
                    $('#total-flowfiles-size').text(nfCommon.formatDataSize(0));
                });

                // adjust the table size
                nfQueueListing.resetTableSize();

                // store the connection for access later
                $('#queue-listing-table').data('connection', connection);
            });
        }
    };

    return nfQueueListing;
}));