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

// Define a common utility class used across the entire application.
(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        define(['jquery',
                'd3',
                'nf.Storage',
                'lodash-core',
                'moment'],
            function ($, d3, nfStorage, _, moment) {
                return (nf.Common = factory($, d3, nfStorage, _, moment));
            });
    } else if (typeof exports === 'object' && typeof module === 'object') {
        module.exports = (nf.Common = factory(require('jquery'),
            require('d3'),
            require('nf.Storage'),
            require('lodash-core'),
            require('moment')));
    } else {
        nf.Common = factory(root.$,
            root.d3,
            root.nf.Storage,
            root._,
            root.moment);
    }
}(this, function ($, d3, nfStorage, _, moment) {
    'use strict';

    $(document).ready(function () {
        // preload the image for the error page - this is preloaded because the system
        // may be unavailable to return the image when the error page is rendered
        var imgSrc = 'images/bg-error.png';
        $('<img/>').attr('src', imgSrc).on('load', function () {
            $('div.message-pane').css('background-image', imgSrc);
        });

        // mouse over for links
        $(document).on('mouseenter', 'span.link', function () {
            $(this).addClass('link-over');
        }).on('mouseleave', 'span.link', function () {
            $(this).removeClass('link-over');
        });

        // setup custom checkbox
        $(document).on('click', 'div.nf-checkbox', function () {
            var checkbox = $(this);
            var transitionToChecked = checkbox.hasClass('checkbox-unchecked');

            if (transitionToChecked) {
                checkbox.removeClass('checkbox-unchecked').addClass('checkbox-checked');
            } else {
                checkbox.removeClass('checkbox-checked').addClass('checkbox-unchecked');
            }
            // emit a state change event
            checkbox.trigger('change', {
                isChecked: transitionToChecked
            });
        });

        // setup click areas for custom checkboxes
        $(document).on('click', '.nf-checkbox-label', function (e) {
            $(e.target).parent().find('.nf-checkbox').click();
        });


        // show the loading icon when appropriate
        $(document).ajaxStart(function () {
            // show the loading indicator
            $('div.loading-container').addClass('ajax-loading');
        }).ajaxStop(function () {
            // hide the loading indicator
            $('div.loading-container').removeClass('ajax-loading');
        });

        // shows the logout link in the message-pane when appropriate and schedule token refresh
        if (nfStorage.getItem('jwt') !== null) {
            $('#user-logout-container').css('display', 'block');
            nfCommon.scheduleTokenRefresh();
        }

        // handle logout
        $('#user-logout').on('click', function () {
            $.ajax({
                type: 'DELETE',
                url: '../nifi-api/access/logout',
            }).done(function () {
                nfStorage.removeItem("jwt");
                window.location = '../nifi/logout';
            }).fail(nfErrorHandler.handleAjaxError);
        });

        // handle home
        $('#user-home').on('click', function () {
            if (top !== window) {
                parent.window.location = '../nifi';
            } else {
                window.location = '../nifi';
            }
        });
    });

    // interval for cancelling token refresh when necessary
    var tokenRefreshInterval = null;

    var policyTypeListing = [{
        text: 'view the user interface',
        value: 'flow',
        description: 'Allows users to view the user interface'
    }, {
        text: 'access the controller',
        value: 'controller',
        description: 'Allows users to view/modify the controller including Reporting Tasks, Controller Services, Parameter Contexts, and Nodes in the Cluster'
    }, {
        text: 'access parameter contexts',
        value: 'parameter-contexts',
        description: 'Allows users to view/modify Parameter Contexts'
    }, {
        text: 'query provenance',
        value: 'provenance',
        description: 'Allows users to submit a Provenance Search and request Event Lineage'
    }, {
        text: 'access restricted components',
        value: 'restricted-components',
        description: 'Allows users to create/modify restricted components assuming other permissions are sufficient'
    }, {
        text: 'access all policies',
        value: 'policies',
        description: 'Allows users to view/modify the policies for all components'
    }, {
        text: 'access users/user groups',
        value: 'tenants',
        description: 'Allows users to view/modify the users and user groups'
    }, {
        text: 'retrieve site-to-site details',
        value: 'site-to-site',
        description: 'Allows other NiFi instances to retrieve Site-To-Site details of this NiFi'
    }, {
        text: 'view system diagnostics',
        value: 'system',
        description: 'Allows users to view System Diagnostics'
    }, {
        text: 'proxy user requests',
        value: 'proxy',
        description: 'Allows proxy machines to send requests on the behalf of others'
    }, {
        text: 'access counters',
        value: 'counters',
        description: 'Allows users to view/modify Counters'
    }];

    var nfCommon = {
        ANONYMOUS_USER_TEXT: 'Anonymous user',

        config: {
            sensitiveText: 'Sensitive value set',
            tooltipConfig: {
                style: {
                    classes: 'nifi-tooltip'
                },
                show: {
                    solo: true,
                    effect: function (offset) {
                        $(this).slideDown(100);
                    }
                },
                hide: {
                    effect: function (offset) {
                        $(this).slideUp(100);
                    }
                },
                position: {
                    at: 'top center',
                    my: 'bottom center'
                }
            }
        },

        /**
         * Determines if the current broswer supports SVG.
         */
        SUPPORTS_SVG: !!document.createElementNS && !!document.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGRect,

        /**
         * The current user.
         */
        currentUser: undefined,

        /**
         * Sorts the specified version strings.
         *
         * @param aRawVersion version string
         * @param bRawVersion version string
         * @returns {number} negative if a before b, positive if a after b, 0 otherwise
         */
        sortVersion: function (aRawVersion, bRawVersion) {
            if (aRawVersion === bRawVersion) {
                return 0;
            }

            // attempt to parse the raw strings
            var aTokens = aRawVersion.split(/-/);
            var bTokens = bRawVersion.split(/-/);

            // ensure there is at least one token
            if (aTokens.length >= 1 && bTokens.length >= 1) {
                var aVersionTokens = aTokens[0].split(/\./);
                var bVersionTokens = bTokens[0].split(/\./);

                // ensure both versions have at least one token
                if (aVersionTokens.length >= 1 && bVersionTokens.length >= 1) {
                    // find the number of tokens a and b have in common
                    var commonTokenLength = Math.min(aVersionTokens.length, bVersionTokens.length);

                    // consider all tokens in common
                    for (var i = 0; i < commonTokenLength; i++) {
                        var aVersionSegment = parseInt(aVersionTokens[i], 10);
                        var bVersionSegment = parseInt(bVersionTokens[i], 10);

                        // if both are non numeric, consider the next token
                        if (isNaN(aVersionSegment) && isNaN(bVersionSegment)) {
                            continue;
                        }  else if (isNaN(aVersionSegment)) {
                            // NaN is considered less
                            return -1;
                        } else if (isNaN(bVersionSegment)) {
                            // NaN is considered less
                            return 1;
                        }

                        // if a version at any point does not match
                        if (aVersionSegment !== bVersionSegment) {
                            return aVersionSegment - bVersionSegment;
                        }
                    }

                    if (aVersionTokens.length === bVersionTokens.length) {
                        if (aTokens.length === bTokens.length) {
                            // same version for all tokens so consider the trailing bits (1.1-RC vs 1.1-SNAPSHOT)
                            var aExtraBits = nfCommon.substringAfterFirst(aRawVersion, aTokens[0]);
                            var bExtraBits = nfCommon.substringAfterFirst(bRawVersion, bTokens[0]);
                            return aExtraBits === bExtraBits ? 0 : aExtraBits > bExtraBits ? 1 : -1;
                        } else {
                            // in this case, extra bits means it's consider less than no extra bits (1.1 vs 1.1-SNAPSHOT)
                            return bTokens.length - aTokens.length;
                        }
                    } else {
                        // same version for all tokens in common (ie 1.1 vs 1.1.1)
                        return aVersionTokens.length - bVersionTokens.length;
                    }
                } else if (aVersionTokens.length >= 1) {
                    // presence of version tokens is considered greater
                    return 1;
                } else if (bVersionTokens.length >= 1) {
                    // presence of version tokens is considered greater
                    return -1;
                } else {
                    return 0;
                }
            } else if (aTokens.length >= 1) {
                // presence of tokens is considered greater
                return 1;
            } else if (bTokens.length >= 1) {
                // presence of tokens is considered greater
                return -1;
            } else {
                return 0;
            }
        },

        /**
         * Sorts the specified type data using the specified sort details.
         *
         * @param {object} sortDetails
         * @param {object} data
         */
        sortType: function (sortDetails, data) {
            // compares two bundles
            var compareBundle = function (a, b) {
                var aBundle = nfCommon.formatBundle(a.bundle);
                var bBundle = nfCommon.formatBundle(b.bundle);
                return aBundle === bBundle ? 0 : aBundle > bBundle ? 1 : -1;
            };

            // defines a function for sorting
            var comparer = function (a, b) {
                if (sortDetails.columnId === 'version') {
                    var aVersion = nfCommon.isDefinedAndNotNull(a.bundle[sortDetails.columnId]) ? a.bundle[sortDetails.columnId] : '';
                    var bVersion = nfCommon.isDefinedAndNotNull(b.bundle[sortDetails.columnId]) ? b.bundle[sortDetails.columnId] : '';
                    var versionResult = nfCommon.sortVersion(aVersion, bVersion);
                    return versionResult === 0 ? compareBundle(a, b) : versionResult;
                } else if (sortDetails.columnId === 'type') {
                    var aType = nfCommon.substringAfterLast(a[sortDetails.columnId], '.');
                    var bType = nfCommon.substringAfterLast(b[sortDetails.columnId], '.');
                    return aType === bType ? 0 : aType > bType ? 1 : -1;
                } else {
                    var aString = nfCommon.isDefinedAndNotNull(a[sortDetails.columnId]) ? a[sortDetails.columnId] : '';
                    var bString = nfCommon.isDefinedAndNotNull(b[sortDetails.columnId]) ? b[sortDetails.columnId] : '';
                    return aString === bString ? compareBundle(a, b) : aString > bString ? 1 : -1;
                }
            };

            // perform the sort
            data.sort(comparer, sortDetails.sortAsc);
        },

        /**
         * Formats type of a component for a new instance dialog.
         *
         * @param row
         * @param cell
         * @param value
         * @param columnDef
         * @param dataContext
         * @returns {string}
         */
        typeFormatter: function (row, cell, value, columnDef, dataContext) {
            var markup = '';

            // restriction
            if (dataContext.restricted === true) {
                markup += '<div class="view-usage-restriction fa fa-shield"></div><span class="hidden row-id">' + nfCommon.escapeHtml(dataContext.id) + '</span>';
            } else {
                markup += '<div class="fa"></div>';
            }

            // type
            markup += nfCommon.escapeHtml(value);

            return markup;
        },

        /**
         * Escapes any malicious HTML characters from the value.
         *
         * @param row
         * @param cell
         * @param value
         * @param columnDef
         * @param dataContext
         * @returns {string}
         */
        genericValueFormatter: function (row, cell, value, columnDef, dataContext) {
            return nfCommon.escapeHtml(value);
        },

        /**
         * Formats the bundle of a component type for the new instance dialog.
         *
         * @param row
         * @param cell
         * @param value
         * @param columnDef
         * @param dataContext
         * @returns {string}
         */
        typeBundleFormatter: function (row, cell, value, columnDef, dataContext) {
            return nfCommon.escapeHtml(nfCommon.formatBundle(dataContext.bundle));
        },

        /**
         * Formats the bundle of a component type for the new instance dialog.
         *
         * @param row
         * @param cell
         * @param value
         * @param columnDef
         * @param dataContext
         * @returns {string}
         */
        typeVersionFormatter: function (row, cell, value, columnDef, dataContext) {
            var markup = '';

            if (nfCommon.isDefinedAndNotNull(dataContext.bundle)) {
                markup += ('<div style="float: left;">' + nfCommon.escapeHtml(dataContext.bundle.version) + '</div>');
            } else {
                markup += '<div style="float: left;">unversioned</div>';
            }

            if (!nfCommon.isEmpty(dataContext.controllerServiceApis)) {
                markup += '<div class="controller-service-apis fa fa-list" title="Compatible Controller Service" style="margin-left: 4px;"></div><span class="hidden row-id">' + nfCommon.escapeHtml(dataContext.id) + '</span>';
            }

            markup += '<div class="clear"></div>';

            return markup;
        },

        /**
         * Formatter for the type column.
         *
         * @param {type} row
         * @param {type} cell
         * @param {type} value
         * @param {type} columnDef
         * @param {type} dataContext
         * @returns {String}
         */
        instanceTypeFormatter: function (row, cell, value, columnDef, dataContext) {
            if (!dataContext.permissions.canRead) {
                return '';
            }

            return nfCommon.escapeHtml(nfCommon.formatType(dataContext.component));
        },

        /**
         * Formats the bundle of a component instance for the component listing table.
         *
         * @param row
         * @param cell
         * @param value
         * @param columnDef
         * @param dataContext
         * @returns {string}
         */
        instanceBundleFormatter: function (row, cell, value, columnDef, dataContext) {
            if (!dataContext.permissions.canRead) {
                return '';
            }

            return nfCommon.typeBundleFormatter(row, cell, value, columnDef, dataContext.component);
        },

        /**
         * Gets the version control tooltip.
         *
         * @param versionControlInformation
         */
        getVersionControlTooltip: function (versionControlInformation) {
            return versionControlInformation.stateExplanation;
        },

        /**
         * Formats the class name of this component.
         *
         * @param dataContext component datum
         */
        formatClassName: function (dataContext) {
            return nfCommon.substringAfterLast(dataContext.type, '.');
        },

        /**
         * Formats the type of this component.
         *
         * @param dataContext component datum
         */
        formatType: function (dataContext) {
            var typeString = nfCommon.formatClassName(dataContext);
            if (dataContext.bundle.version !== 'unversioned') {
                typeString += (' ' + dataContext.bundle.version);
            }
            return typeString;
        },

        /**
         * Formats the bundle label.
         *
         * @param bundle
         */
        formatBundle: function (bundle) {
            var groupString = '';
            if (bundle.group !== 'default') {
                groupString = bundle.group + ' - ';
            }
            return groupString + bundle.artifact;
        },

        /**
         * Sets the current user.
         *
         * @param currentUser
         */
        setCurrentUser: function (currentUser) {
            nfCommon.currentUser = currentUser;
        },

        /**
         * Automatically refresh tokens by checking once an hour if its going to expire soon.
         */
        scheduleTokenRefresh: function () {
            // if we are currently polling for token refresh, cancel it
            if (tokenRefreshInterval !== null) {
                clearInterval(tokenRefreshInterval);
            }

            // set the interval to one hour
            var interval = nfCommon.MILLIS_PER_MINUTE;

            var checkExpiration = function () {
                var expiration = nfStorage.getItemExpiration('jwt');

                // ensure there is an expiration and token present
                if (expiration !== null) {
                    var expirationDate = new Date(expiration);
                    var now = new Date();

                    // get the time remainging plus a little bonus time to reload the token
                    var timeRemaining = expirationDate.valueOf() - now.valueOf() - (30 * nfCommon.MILLIS_PER_SECOND);
                    if (timeRemaining < interval) {
                        if ($('#current-user').text() !== nfCommon.ANONYMOUS_USER_TEXT && !$('#anonymous-user-alert').is(':visible')) {
                            // if the token will expire before the next interval minus some bonus time, notify the user to re-login
                            $('#anonymous-user-alert').show().qtip($.extend({}, nfCommon.config.tooltipConfig, {
                                content: 'Your session will expire soon. Please log in again to avoid being automatically logged out.',
                                position: {
                                    my: 'top right',
                                    at: 'bottom left'
                                }
                            }));
                        }
                    }
                }
            };

            // perform initial check
            checkExpiration();

            // schedule subsequent checks
            tokenRefreshInterval = setInterval(checkExpiration, interval);
        },

        /**
         * Sets the anonymous user label.
         */
        setAnonymousUserLabel: function () {
            var anonymousUserAlert = $('#anonymous-user-alert');
            if (anonymousUserAlert.data('qtip')) {
                anonymousUserAlert.qtip('api').destroy(true);
            }

            // alert user's of anonymous access
            anonymousUserAlert.show().qtip($.extend({}, nfCommon.config.tooltipConfig, {
                content: 'You are accessing with limited authority. Log in or request an account to access with additional authority granted to you by an administrator.',
                position: {
                    my: 'top right',
                    at: 'bottom left'
                }
            }));

            // render the anonymous user text
            $('#current-user').text(nfCommon.ANONYMOUS_USER_TEXT).show();
        },

        /**
         * Extracts the subject from the specified jwt. If the jwt is not as expected
         * an empty string is returned.
         *
         * @param {string} jwt
         * @returns {string}
         */
        getJwtPayload: function (jwt) {
            if (nfCommon.isDefinedAndNotNull(jwt)) {
                var segments = jwt.split(/\./);
                if (segments.length !== 3) {
                    return '';
                }

                var rawPayload = $.base64.atob(segments[1]);
                var payload = JSON.parse(rawPayload);

                if (nfCommon.isDefinedAndNotNull(payload)) {
                    return payload;
                } else {
                    return null;
                }
            }

            return null;
        },

        /**
         * Determines whether the current user can version flows.
         */
        canVersionFlows: function () {
            if (nfCommon.isDefinedAndNotNull(nfCommon.currentUser)) {
                return nfCommon.currentUser.canVersionFlows === true;
            } else {
                return false;
            }
        },

        /**
         * Determines whether the current user can access provenance.
         *
         * @returns {boolean}
         */
        canAccessProvenance: function () {
            if (nfCommon.isDefinedAndNotNull(nfCommon.currentUser)) {
                return nfCommon.currentUser.provenancePermissions.canRead === true;
            } else {
                return false;
            }
        },

        /**
         * Determines whether the current user can access restricted components.
         *
         * @returns {boolean}
         */
        canAccessRestrictedComponents: function () {
            if (nfCommon.isDefinedAndNotNull(nfCommon.currentUser)) {
                return nfCommon.currentUser.restrictedComponentsPermissions.canWrite === true;
            } else {
                return false;
            }
        },

        /**
         * Determines whether the current user can access the specific explicit component restrictions.
         *
         * @param {object} explicitRestrictions
         * @returns {boolean}
         */
        canAccessComponentRestrictions: function (explicitRestrictions) {
            if (nfCommon.isDefinedAndNotNull(nfCommon.currentUser)) {
                if (nfCommon.currentUser.restrictedComponentsPermissions.canWrite === true) {
                    return true;
                }

                var satisfiesRequiredPermission = function (requiredPermission) {
                    if (nfCommon.isEmpty(nfCommon.currentUser.componentRestrictionPermissions)) {
                        return false;
                    }

                    var hasPermission = false;

                    $.each(nfCommon.currentUser.componentRestrictionPermissions, function (_, componentRestrictionPermission) {
                        if (componentRestrictionPermission.requiredPermission.id === requiredPermission.id) {
                            if (componentRestrictionPermission.permissions.canWrite === true) {
                                hasPermission = true;
                                return false;
                            }
                        }
                    });

                    return hasPermission;
                };

                var satisfiesRequiredPermissions = true;

                if (nfCommon.isEmpty(explicitRestrictions)) {
                    satisfiesRequiredPermissions = false;
                } else {
                    $.each(explicitRestrictions, function (_, explicitRestriction) {
                        if (!satisfiesRequiredPermission(explicitRestriction.requiredPermission)) {
                            satisfiesRequiredPermissions = false;
                            return false;
                        }
                    });
                }

                return satisfiesRequiredPermissions;
            } else {
                return false;
            }
        },

        /**
         * Determines whether the current user can access counters.
         *
         * @returns {boolean}
         */
        canAccessCounters: function () {
            if (nfCommon.isDefinedAndNotNull(nfCommon.currentUser)) {
                return nfCommon.currentUser.countersPermissions.canRead === true;
            } else {
                return false;
            }
        },

        /**
         * Determines whether the current user can modify counters.
         *
         * @returns {boolean}
         */
        canModifyCounters: function () {
            if (nfCommon.isDefinedAndNotNull(nfCommon.currentUser)) {
                return nfCommon.currentUser.countersPermissions.canRead === true && nfCommon.currentUser.countersPermissions.canWrite === true;
            } else {
                return false;
            }
        },

        /**
         * Determines whether the current user can access tenants.
         *
         * @returns {boolean}
         */
        canAccessTenants: function () {
            if (nfCommon.isDefinedAndNotNull(nfCommon.currentUser)) {
                return nfCommon.currentUser.tenantsPermissions.canRead === true;
            } else {
                return false;
            }
        },

        /**
         * Determines whether the current user can modify tenants.
         *
         * @returns {boolean}
         */
        canModifyTenants: function () {
            if (nfCommon.isDefinedAndNotNull(nfCommon.currentUser)) {
                return nfCommon.currentUser.tenantsPermissions.canRead === true && nfCommon.currentUser.tenantsPermissions.canWrite === true;
            } else {
                return false;
            }
        },

        /**
         * Determines whether the current user can modify parameter contexts.
         *
         * @returns {boolean}
         */
        canModifyParameterContexts: function () {
            if (nfCommon.isDefinedAndNotNull(nfCommon.currentUser)) {
                return nfCommon.currentUser.parameterContextPermissions.canRead === true && nfCommon.currentUser.parameterContextPermissions.canWrite === true;
            } else {
                return false;
            }
        },

        /**
         * Determines whether the current user can access counters.
         *
         * @returns {boolean}
         */
        canAccessPolicies: function () {
            if (nfCommon.isDefinedAndNotNull(nfCommon.currentUser)) {
                return nfCommon.currentUser.policiesPermissions.canRead === true;
            } else {
                return false;
            }
        },

        /**
         * Determines whether the current user can modify counters.
         *
         * @returns {boolean}
         */
        canModifyPolicies: function () {
            if (nfCommon.isDefinedAndNotNull(nfCommon.currentUser)) {
                return nfCommon.currentUser.policiesPermissions.canRead === true && nfCommon.currentUser.policiesPermissions.canWrite === true;
            } else {
                return false;
            }
        },

        /**
         * Determines whether the current user can access the controller.
         *
         * @returns {boolean}
         */
        canAccessController: function () {
            if (nfCommon.isDefinedAndNotNull(nfCommon.currentUser)) {
                return nfCommon.currentUser.controllerPermissions.canRead === true;
            } else {
                return false;
            }
        },

        /**
         * Determines whether the current user can modify the controller.
         *
         * @returns {boolean}
         */
        canModifyController: function () {
            if (nfCommon.isDefinedAndNotNull(nfCommon.currentUser)) {
                return nfCommon.currentUser.controllerPermissions.canRead === true && nfCommon.currentUser.controllerPermissions.canWrite === true;
            } else {
                return false;
            }
        },

        /**
         * Determines whether the current user can access system diagnostics.
         *
         * @returns {boolean}
         */
        canAccessSystem: function () {
            if (nfCommon.isDefinedAndNotNull(nfCommon.currentUser)) {
                return nfCommon.currentUser.systemPermissions.canRead === true;
            } else {
                return false;
            }
        },

        /**
         * Adds a mouse over effect for the specified selector using
         * the specified styles.
         *
         * @argument {string} selector      The selector for the element to add a hover effect for
         * @argument {string} normalStyle   The css style for the normal state
         * @argument {string} overStyle     The css style for the over state
         */
        addHoverEffect: function (selector, normalStyle, overStyle) {
            $(document).on('mouseenter', selector, function () {
                $(this).removeClass(normalStyle).addClass(overStyle);
            }).on('mouseleave', selector, function () {
                $(this).removeClass(overStyle).addClass(normalStyle);
            });
            return $(selector).addClass(normalStyle);
        },

        /**
         * Determine if an `element` has content overflow and adds the `.scrollable` class if it does.
         *
         * @param {HTMLElement} element The DOM element to toggle .scrollable upon.
         */
        toggleScrollable: function (element) {
            if ($(element).is(':visible')) {
                if (element.offsetHeight < element.scrollHeight ||
                    element.offsetWidth < element.scrollWidth) {
                    // your element has overflow
                    $(element).addClass('scrollable');
                } else {
                    $(element).removeClass('scrollable');
                }
            }
        },

        /**
         * Determines the contrast color of a given hex color.
         *
         * @param {string} hex  The hex color to test.
         * @returns {string} The contrasting color string.
         */
        determineContrastColor: function (hex) {
            if (parseInt(hex, 16) > 0xffffff / 1.5) {
                return '#000000';
            }
            return '#ffffff';
        },

        /**
         * Shows the logout link if appropriate.
         */
        updateLogoutLink: function () {
            if (nfStorage.getItem('jwt') !== null) {
                $('#user-logout-container').css('display', 'block');
            } else {
                $('#user-logout-container').css('display', 'none');
            }
        },

        /**
         * Returns whether a content viewer has been configured.
         *
         * @returns {boolean}
         */
        isContentViewConfigured: function () {
            var contentViewerUrl = $('#nifi-content-viewer-url').text();
            return !nfCommon.isBlank(contentViewerUrl);
        },

        /**
         * Populates the specified field with the specified value. If the value is
         * undefined, the field will read 'No value set.' If the value is an empty
         * string, the field will read 'Empty string set.'
         *
         * @argument {string} target        The dom Id of the target
         * @argument {string} value         The value
         */
        populateField: function (target, value) {
            if (nfCommon.isUndefined(value) || nfCommon.isNull(value)) {
                return $('#' + target).addClass('unset').text('No value set');
            } else if (value === '') {
                return $('#' + target).addClass('blank').text('Empty string set');
            } else {
                return $('#' + target).text(value);
            }
        },

        /**
         * Clears the specified field. Removes any style that may have been applied
         * by a preceeding call to populateField.
         *
         * @argument {string} target        The dom Id of the target
         */
        clearField: function (target) {
            return $('#' + target).removeClass('unset blank').text('');
        },

        /**
         * Cleans up any tooltips that have been created for the specified container.
         *
         * @param {jQuery} container
         * @param {string} tooltipTarget
         */
        cleanUpTooltips: function (container, tooltipTarget) {
            container.find(tooltipTarget).each(function () {
                var tip = $(this);
                if (tip.data('qtip')) {
                    var api = tip.qtip('api');
                    api.destroy(true);
                }
            });
        },

        /**
         * Formats the tooltip for the specified property.
         *
         * @param {object} propertyDescriptor      The property descriptor
         * @param {object} propertyHistory         The property history
         * @returns {string}
         */
        formatPropertyTooltip: function (propertyDescriptor, propertyHistory) {
            var tipContent = [];

            // show the property description if applicable
            if (nfCommon.isDefinedAndNotNull(propertyDescriptor)) {
                if (!nfCommon.isBlank(propertyDescriptor.description)) {
                    tipContent.push(nfCommon.escapeHtml(propertyDescriptor.description));
                }
                if (!nfCommon.isBlank(propertyDescriptor.defaultValue)) {
                    tipContent.push('<b>Default value:</b> ' + nfCommon.escapeHtml(propertyDescriptor.defaultValue));
                }
                if (!nfCommon.isBlank(propertyDescriptor.supportsEl)) {
                    tipContent.push('<b>Expression language scope:</b> ' + nfCommon.escapeHtml(propertyDescriptor.expressionLanguageScope));
                }
                if (!nfCommon.isBlank(propertyDescriptor.sensitive)) {
                    tipContent.push('<b>Sensitive property:</b> ' + nfCommon.escapeHtml(propertyDescriptor.sensitive));
                }
                if (!nfCommon.isBlank(propertyDescriptor.identifiesControllerService)) {
                    var formattedType = nfCommon.formatType({
                        'type': propertyDescriptor.identifiesControllerService,
                        'bundle': propertyDescriptor.identifiesControllerServiceBundle
                    });
                    var formattedBundle = nfCommon.formatBundle(propertyDescriptor.identifiesControllerServiceBundle);
                    tipContent.push('<b>Requires Controller Service:</b> ' + nfCommon.escapeHtml(formattedType + ' from ' + formattedBundle));
                }
            }

            if (nfCommon.isDefinedAndNotNull(propertyHistory)) {
                if (!nfCommon.isEmpty(propertyHistory.previousValues)) {
                    var history = [];
                    $.each(propertyHistory.previousValues, function (_, previousValue) {
                        history.push('<li>' + nfCommon.escapeHtml(previousValue.previousValue) + ' - ' + nfCommon.escapeHtml(previousValue.timestamp) + ' (' + nfCommon.escapeHtml(previousValue.userIdentity) + ')</li>');
                    });
                    tipContent.push('<b>History:</b><ul class="property-info">' + history.join('') + '</ul>');
                }
            }

            if (tipContent.length > 0) {
                return tipContent.join('<br/><br/>');
            } else {
                return null;
            }
        },

        /**
         * Formats the specified property (name and value) accordingly.
         *
         * @argument {string} name      The name of the property
         * @argument {string} value     The value of the property
         */
        formatProperty: function (name, value) {
            return '<div><span class="label">' + nfCommon.formatValue(name) + ': </span>' + nfCommon.formatValue(value) + '</div>';
        },

        /**
         * Formats the specified value accordingly.
         *
         * @argument {string} value     The value of the property
         */
        formatValue: function (value) {
            if (nfCommon.isDefinedAndNotNull(value)) {
                if (value === '') {
                    return '<span class="blank" style="font-size: 13px; padding-top: 2px;">Empty string set</span>';
                } else {
                    return nfCommon.escapeHtml(value);
                }
            } else {
                return '<span class="unset" style="font-size: 13px; padding-top: 2px;">No value set</span>';
            }
        },

        /**
         * HTML escapes the specified string. If the string is null
         * or undefined, an empty string is returned.
         *
         * @returns {string}
         */
        escapeHtml: (function () {
            var entityMap = {
                '&': '&amp;',
                '<': '&lt;',
                '>': '&gt;',
                '"': '&quot;',
                "'": '&#39;',
                '/': '&#x2f;'
            };

            return function (string) {
                if (nfCommon.isDefinedAndNotNull(string)) {
                    return String(string).replace(/[&<>"'\/]/g, function (s) {
                        return entityMap[s];
                    });
                } else {
                    return '';
                }
            };
        }()),

        /**
         * Determines if the specified property is sensitive.
         *
         * @argument {object} propertyDescriptor        The property descriptor
         */
        isSensitiveProperty: function (propertyDescriptor) {
            if (nfCommon.isDefinedAndNotNull(propertyDescriptor)) {
                return propertyDescriptor.sensitive === true;
            } else {
                return false;
            }
        },

        /**
         * Determines if the specified property is required.
         *
         * @param {object} propertyDescriptor           The property descriptor
         */
        isRequiredProperty: function (propertyDescriptor) {
            if (nfCommon.isDefinedAndNotNull(propertyDescriptor)) {
                return propertyDescriptor.required === true;
            } else {
                return false;
            }
        },

        /**
         * Determines if the specified property is required.
         *
         * @param {object} propertyDescriptor           The property descriptor
         */
        isDynamicProperty: function (propertyDescriptor) {
            if (nfCommon.isDefinedAndNotNull(propertyDescriptor)) {
                return propertyDescriptor.dynamic === true;
            } else {
                return false;
            }
        },

        /**
         * Gets the allowable values for the specified property.
         *
         * @argument {object} propertyDescriptor        The property descriptor
         */
        getAllowableValues: function (propertyDescriptor) {
            if (nfCommon.isDefinedAndNotNull(propertyDescriptor)) {
                return propertyDescriptor.allowableValues;
            } else {
                return null;
            }
        },

        /**
         * Returns whether the specified property supports EL.
         *
         * @param {object} propertyDescriptor           The property descriptor
         */
        supportsEl: function (propertyDescriptor) {
            if (nfCommon.isDefinedAndNotNull(propertyDescriptor)) {
                return propertyDescriptor.supportsEl === true;
            } else {
                return false;
            }
        },

        /**
         * Formats the specified array as an unordered list. If the array is not an
         * array, null is returned.
         *
         * @argument {array} array      The array to convert into an unordered list
         */
        formatUnorderedList: function (array) {
            if ($.isArray(array)) {
                var ul = $('<ul class="result"></ul>');
                $.each(array, function (_, item) {
                    var li = $('<li></li>').appendTo(ul);
                    if (item instanceof jQuery) {
                        li.append(item);
                    } else {
                        li.text(item);
                    }
                });
                return ul;
            } else {
                return null;
            }
        },

        /**
         * Extracts the contents of the specified str after the last strToFind. If the
         * strToFind is not found or the last part of the str, an empty string is
         * returned.
         *
         * @argument {string} str       The full string
         * @argument {string} strToFind The substring to find
         */
        substringAfterLast: function (str, strToFind) {
            var result = '';
            var indexOfStrToFind = str.lastIndexOf(strToFind);
            if (indexOfStrToFind >= 0) {
                var indexAfterStrToFind = indexOfStrToFind + strToFind.length;
                if (indexAfterStrToFind < str.length) {
                    result = str.substr(indexAfterStrToFind);
                }
            }
            return result;
        },

        /**
         * Extracts the contents of the specified str after the strToFind. If the
         * strToFind is not found or the last part of the str, an empty string is
         * returned.
         *
         * @argument {string} str       The full string
         * @argument {string} strToFind The substring to find
         */
        substringAfterFirst: function (str, strToFind) {
            var result = '';
            var indexOfStrToFind = str.indexOf(strToFind);
            if (indexOfStrToFind >= 0) {
                var indexAfterStrToFind = indexOfStrToFind + strToFind.length;
                if (indexAfterStrToFind < str.length) {
                    result = str.substr(indexAfterStrToFind);
                }
            }
            return result;
        },

        /**
         * Extracts the contents of the specified str before the last strToFind. If the
         * strToFind is not found or the first part of the str, an empty string is
         * returned.
         *
         * @argument {string} str       The full string
         * @argument {string} strToFind The substring to find
         */
        substringBeforeLast: function (str, strToFind) {
            var result = '';
            var indexOfStrToFind = str.lastIndexOf(strToFind);
            if (indexOfStrToFind >= 0) {
                result = str.substr(0, indexOfStrToFind);
            }
            return result;
        },

        /**
         * Extracts the contents of the specified str before the strToFind. If the
         * strToFind is not found or the first path of the str, an empty string is
         * returned.
         *
         * @argument {string} str       The full string
         * @argument {string} strToFind The substring to find
         */
        substringBeforeFirst: function (str, strToFind) {
            var result = '';
            var indexOfStrToFind = str.indexOf(strToFind);
            if (indexOfStrToFind >= 0) {
                result = str.substr(0, indexOfStrToFind);
            }
            return result
        },

        /**
         * Updates the mouse pointer.
         *
         * @argument {string} domId         The id of the element for the new cursor style
         * @argument {boolean} isMouseOver  Whether or not the mouse is over the element
         */
        setCursor: function (domId, isMouseOver) {
            if (isMouseOver) {
                $('#' + domId).addClass('pointer');
            } else {
                $('#' + domId).removeClass('pointer');
            }
        },

        /**
         * Constants for time duration formatting.
         */
        MILLIS_PER_DAY: 86400000,
        MILLIS_PER_HOUR: 3600000,
        MILLIS_PER_MINUTE: 60000,
        MILLIS_PER_SECOND: 1000,

        /**
         * Constants for combo options.
         */
        loadBalanceStrategyOptions: [{
                text: 'Do not load balance',
                value: 'DO_NOT_LOAD_BALANCE',
                description: 'Do not load balance FlowFiles between nodes in the cluster.'
            }, {
                text: 'Partition by attribute',
                value: 'PARTITION_BY_ATTRIBUTE',
                description: 'Determine which node to send a given FlowFile to based on the value of a user-specified FlowFile Attribute.'
                                + ' All FlowFiles that have the same value for said Attribute will be sent to the same node in the cluster.'
            }, {
                text: 'Round robin',
                value: 'ROUND_ROBIN',
                description: 'FlowFiles will be distributed to nodes in the cluster in a Round-Robin fashion. However, if a node in the cluster is not able to receive data as fast as other nodes,'
                                + ' that node may be skipped in one or more iterations in order to maximize throughput of data distribution across the cluster.'
            }, {
                text: 'Single node',
                value: 'SINGLE_NODE',
                description: 'All FlowFiles will be sent to the same node. Which node they are sent to is not defined.'
        }],

        loadBalanceCompressionOptions: [{
                text: 'Do not compress',
                value: 'DO_NOT_COMPRESS',
                description: 'FlowFiles will not be compressed'
            }, {
                text: 'Compress attributes only',
                value: 'COMPRESS_ATTRIBUTES_ONLY',
                description: 'FlowFiles\' attributes will be compressed, but the FlowFiles\' contents will not be'
            }, {
                text: 'Compress attributes and content',
                value: 'COMPRESS_ATTRIBUTES_AND_CONTENT',
                description: 'FlowFiles\' attributes and content will be compressed'
        }],

        /**
         * Formats the specified duration.
         *
         * @param {integer} duration in millis
         */
        formatDuration: function (duration) {
            // don't support sub millisecond resolution
            duration = duration < 1 ? 0 : duration;

            // determine the number of days in the specified duration
            var days = duration / nfCommon.MILLIS_PER_DAY;
            days = days >= 1 ? parseInt(days, 10) : 0;
            duration %= nfCommon.MILLIS_PER_DAY;

            // remaining duration should be less than 1 day, get number of hours
            var hours = duration / nfCommon.MILLIS_PER_HOUR;
            hours = hours >= 1 ? parseInt(hours, 10) : 0;
            duration %= nfCommon.MILLIS_PER_HOUR;

            // remaining duration should be less than 1 hour, get number of minutes
            var minutes = duration / nfCommon.MILLIS_PER_MINUTE;
            minutes = minutes >= 1 ? parseInt(minutes, 10) : 0;
            duration %= nfCommon.MILLIS_PER_MINUTE;

            // remaining duration should be less than 1 minute, get number of seconds
            var seconds = duration / nfCommon.MILLIS_PER_SECOND;
            seconds = seconds >= 1 ? parseInt(seconds, 10) : 0;

            // remaining duration is the number millis (don't support sub millisecond resolution)
            duration = Math.floor(duration % nfCommon.MILLIS_PER_SECOND);

            // format the time
            var time = nfCommon.pad(hours, 2, '0') +
                ':' +
                nfCommon.pad(minutes, 2, '0') +
                ':' +
                nfCommon.pad(seconds, 2, '0') +
                '.' +
                nfCommon.pad(duration, 3, '0');

            // only include days if appropriate
            if (days > 0) {
                return days + ' days and ' + time;
            } else {
                return time;
            }
        },

        /**
         * Formats a number (in milliseconds) to a human-readable textual description.
         *
         * @param duration number of milliseconds representing the duration
         * @return {string|*} a human-readable string
         */
        formatPredictedDuration: function (duration) {
            if (duration === 0) {
                return 'now';
            }
            return moment.duration(duration, 'ms').humanize();
        },

        /**
         * Constants for formatting data size.
         */
        BYTES_IN_KILOBYTE: 1024,
        BYTES_IN_MEGABYTE: 1048576,
        BYTES_IN_GIGABYTE: 1073741824,
        BYTES_IN_TERABYTE: 1099511627776,

        /**
         * Formats the specified number of bytes into a human readable string.
         *
         * @param {integer} dataSize
         * @returns {string}
         */
        formatDataSize: function (dataSize) {
            // check terabytes
            var dataSizeToFormat = parseFloat(dataSize / nfCommon.BYTES_IN_TERABYTE);
            if (dataSizeToFormat > 1) {
                return dataSizeToFormat.toFixed(2) + " TB";
            }

            // check gigabytes
            dataSizeToFormat = parseFloat(dataSize / nfCommon.BYTES_IN_GIGABYTE);
            if (dataSizeToFormat > 1) {
                return dataSizeToFormat.toFixed(2) + " GB";
            }

            // check megabytes
            dataSizeToFormat = parseFloat(dataSize / nfCommon.BYTES_IN_MEGABYTE);
            if (dataSizeToFormat > 1) {
                return dataSizeToFormat.toFixed(2) + " MB";
            }

            // check kilobytes
            dataSizeToFormat = parseFloat(dataSize / nfCommon.BYTES_IN_KILOBYTE);
            if (dataSizeToFormat > 1) {
                return dataSizeToFormat.toFixed(2) + " KB";
            }

            // default to bytes
            return parseFloat(dataSize).toFixed(2) + " bytes";
        },

        /**
         * Formats the specified integer as a string (adding commas). At this
         * point this does not take into account any locales.
         *
         * @param {integer} integer
         */
        formatInteger: function (integer) {
            var string = integer + '';
            var regex = /(\d+)(\d{3})/;
            while (regex.test(string)) {
                string = string.replace(regex, '$1' + ',' + '$2');
            }
            return nfCommon.escapeHtml(string);
        },

        /**
         * Formats the specified float using two decimal places.
         *
         * @param {float} f
         */
        formatFloat: function (f) {
            if (nfCommon.isUndefinedOrNull(f)) {
                return 0.00 + '';
            }
            return f.toFixed(2) + '';
        },

        /**
         * Pads the specified value to the specified width with the specified character.
         * If the specified value is already wider than the specified width, the original
         * value is returned.
         *
         * @param {integer} value
         * @param {integer} width
         * @param {string} character
         * @returns {string}
         */
        pad: function (value, width, character) {
            var s = value + '';

            // pad until wide enough
            while (s.length < width) {
                s = character + s;
            }

            return s;
        },

        /**
         * Formats the specified DateTime.
         *
         * @param {Date} date
         * @returns {String}
         */
        formatDateTime: function (date) {
            return nfCommon.pad(date.getMonth() + 1, 2, '0') +
                '/' +
                nfCommon.pad(date.getDate(), 2, '0') +
                '/' +
                nfCommon.pad(date.getFullYear(), 2, '0') +
                ' ' +
                nfCommon.pad(date.getHours(), 2, '0') +
                ':' +
                nfCommon.pad(date.getMinutes(), 2, '0') +
                ':' +
                nfCommon.pad(date.getSeconds(), 2, '0') +
                '.' +
                nfCommon.pad(date.getMilliseconds(), 3, '0');
        },

        /**
         * Parses the specified date time into a Date object. The resulting
         * object does not account for timezone and should only be used for
         * performing relative comparisons.
         *
         * @param {string} rawDateTime
         * @returns {Date}
         */
        parseDateTime: function (rawDateTime) {
            // handle non date values
            if (!nfCommon.isDefinedAndNotNull(rawDateTime)) {
                return new Date();
            }
            if (rawDateTime === 'No value set') {
                return new Date();
            }
            if (rawDateTime === 'Empty string set') {
                return new Date();
            }

            // parse the date time
            var dateTime = rawDateTime.split(/ /);

            // ensure the correct number of tokens
            if (dateTime.length !== 3) {
                return new Date();
            }

            // get the date and time
            var date = dateTime[0].split(/\//);
            var time = dateTime[1].split(/:/);

            // ensure the correct number of tokens
            if (date.length !== 3 || time.length !== 3) {
                return new Date();
            }
            var year = parseInt(date[2], 10);
            var month = parseInt(date[0], 10) - 1; // new Date() accepts months 0 - 11
            var day = parseInt(date[1], 10);
            var hours = parseInt(time[0], 10);
            var minutes = parseInt(time[1], 10);

            // detect if there is millis
            var secondsSpec = time[2].split(/\./);
            var seconds = parseInt(secondsSpec[0], 10);
            var milliseconds = 0;
            if (secondsSpec.length === 2) {
                milliseconds = parseInt(secondsSpec[1], 10);
            }
            return new Date(year, month, day, hours, minutes, seconds, milliseconds);
        },

        /**
         * Parses the specified duration and returns the total number of millis.
         *
         * @param {string} rawDuration
         * @returns {number}        The number of millis
         */
        parseDuration: function (rawDuration) {
            var duration = rawDuration.split(/:/);

            // ensure the appropriate number of tokens
            if (duration.length !== 3) {
                return 0;
            }

            // detect if there is millis
            var seconds = duration[2].split(/\./);
            if (seconds.length === 2) {
                return new Date(1970, 0, 1, parseInt(duration[0], 10), parseInt(duration[1], 10), parseInt(seconds[0], 10), parseInt(seconds[1], 10)).getTime();
            } else {
                return new Date(1970, 0, 1, parseInt(duration[0], 10), parseInt(duration[1], 10), parseInt(duration[2], 10), 0).getTime();
            }
        },

        /**
         * Parses the specified size.
         *
         * @param {string} rawSize
         * @returns {int}
         */
        parseSize: function (rawSize) {
            var tokens = rawSize.split(/ /);
            var size = parseFloat(tokens[0].replace(/,/g, ''));
            var units = tokens[1];

            if (units === 'KB') {
                return size * 1024;
            } else if (units === 'MB') {
                return size * 1024 * 1024;
            } else if (units === 'GB') {
                return size * 1024 * 1024 * 1024;
            } else if (units === 'TB') {
                return size * 1024 * 1024 * 1024 * 1024;
            } else {
                return size;
            }
        },

        /**
         * Parses the specified count.
         *
         * @param {string} rawCount
         * @returns {int}
         */
        parseCount: function (rawCount) {
            // extract the count
            var count = rawCount.split(/ /, 1);

            // ensure the string was split successfully
            if (count.length !== 1) {
                return 0;
            }

            // convert the count to an integer
            var intCount = parseInt(count[0].replace(/,/g, ''), 10);

            // ensure it was parsable as an integer
            if (isNaN(intCount)) {
                return 0;
            }
            return intCount;
        },

        /**
         * Determines if the specified object is defined and not null.
         *
         * @argument {object} obj   The object to test
         */
        isDefinedAndNotNull: function (obj) {
            return !nfCommon.isUndefined(obj) && !nfCommon.isNull(obj);
        },

        /**
         * Determines if the specified object is undefined or null.
         *
         * @param {object} obj      The object to test
         */
        isUndefinedOrNull: function (obj) {
            return nfCommon.isUndefined(obj) || nfCommon.isNull(obj);
        },

        /**
         * Determines if the specified object is undefined.
         *
         * @argument {object} obj   The object to test
         */
        isUndefined: function (obj) {
            return typeof obj === 'undefined';
        },

        /**
         * Determines whether the specified string is blank (or null or undefined).
         *
         * @argument {string} str   The string to test
         */
        isBlank: function (str) {
            return nfCommon.isUndefined(str) || nfCommon.isNull(str) || $.trim(str) === '';
        },

        /**
         * Determines if the specified object is null.
         *
         * @argument {object} obj   The object to test
         */
        isNull: function (obj) {
            return obj === null;
        },

        /**
         * Determines if the specified array is empty. If the specified arg is not an
         * array, then true is returned.
         *
         * @argument {array} arr    The array to test
         */
        isEmpty: function (arr) {
            return $.isArray(arr) ? arr.length === 0 : true;
        },

        /**
         * Determines if these are the same bulletins. If both arguments are not
         * arrays, false is returned.
         *
         * @param {array} bulletins
         * @param {array} otherBulletins
         * @returns {boolean}
         */
        doBulletinsDiffer: function (bulletins, otherBulletins) {
            if ($.isArray(bulletins) && $.isArray(otherBulletins)) {
                if (bulletins.length === otherBulletins.length) {
                    for (var i = 0; i < bulletins.length; i++) {
                        if (bulletins[i].id !== otherBulletins[i].id || bulletins[i].canRead !== otherBulletins[i].canRead) {
                            return true;
                        }
                    }
                } else {
                    return true;
                }
            } else if ($.isArray(bulletins) || $.isArray(otherBulletins)) {
                return true;
            }
            return false;
        },

        /**
         * Formats the specified bulletin list.
         *
         * @argument {array} bulletins      The bulletins
         * @return {array}                  The jQuery objects
         */
        getFormattedBulletins: function (bulletinEntities) {
            var formattedBulletinEntities = [];
            $.each(bulletinEntities, function (j, bulletinEntity) {
                if (bulletinEntity.canRead === true) {
                    var bulletin = bulletinEntity.bulletin;

                    // format the node address
                    var nodeAddress = '';
                    if (nfCommon.isDefinedAndNotNull(bulletin.nodeAddress)) {
                        nodeAddress = '-&nbsp;' + nfCommon.escapeHtml(bulletin.nodeAddress) + '&nbsp;-&nbsp;';
                    }

                    // set the bulletin message (treat as text)
                    var bulletinMessage = $('<pre></pre>').css({
                        'white-space': 'pre-wrap'
                    }).text(bulletin.message);

                    // create the bulletin message
                    var formattedBulletin = $('<div>' +
                        nfCommon.escapeHtml(bulletin.timestamp) + '&nbsp;' +
                        nodeAddress + '&nbsp;' +
                        '<b>' + nfCommon.escapeHtml(bulletin.level) + '</b>&nbsp;' +
                        '</div>').append(bulletinMessage);

                    formattedBulletinEntities.push(formattedBulletin);
                }
            });
            return formattedBulletinEntities;
        },

        /**
         * Formats the specified controller service list.
         *
         * @param {array} controllerServiceApis
         * @returns {array}
         */
        getFormattedServiceApis: function (controllerServiceApis) {
            var formattedControllerServiceApis = [];
            $.each(controllerServiceApis, function (i, controllerServiceApi) {
                var formattedType = nfCommon.formatType({
                    'type': controllerServiceApi.type,
                    'bundle': controllerServiceApi.bundle
                });
                var formattedBundle = nfCommon.formatBundle(controllerServiceApi.bundle);
                formattedControllerServiceApis.push($('<div></div>').text(formattedType + ' from ' + formattedBundle));
            });
            return formattedControllerServiceApis;
        },

        /**
         * Formats the specified garbage collections list.
         *
         * @param {array} garbageCollections    The garbage collections
         * @returns {array}                     The formatted messages
         */
        getFormattedGarbageCollections: function (garbageCollections) {
            // sort the garbage collections
            garbageCollections.sort(function (a, b) {
                return b.collectionCount - a.collectionCount;
            });

            var formattedGarbageCollections = [];
            $.each(garbageCollections, function (_, garbageCollection) {
                var name = $('<span style="font-weight: bold;"></span>').text(garbageCollection.name);
                var stats = $('<span></span>').text(' - ' + garbageCollection.collectionCount + ' times (' + garbageCollection.collectionTime + ')');
                var gc = $('<div></div>').append(name).append(stats);
                formattedGarbageCollections.push(gc);
            });
            return formattedGarbageCollections;
        },

        /**
         * Returns whether the specified resource is for a global policy.
         *
         * @param resource
         */
        isGlobalPolicy: function (value) {
            return nfCommon.getPolicyTypeListing(value) !== null;
        },

        /**
         * Gets the policy type for the specified resource.
         *
         * @param value
         * @returns {*}
         */
        getPolicyTypeListing: function (value) {
            return policyTypeListing.find(function (policy) {
                return value === policy.value;
            });
        },

        /**
         * Get component name from an entity safely.
         *
         * @param {object} entity    The component entity
         * @returns {String}         The component name if it can be read, otherwise entity id
         */
        getComponentName: function (entity) {
            return entity.permissions.canRead === true ? entity.component.name : entity.id;
        },

        /**
         * Find the corresponding combo option text from a combo option values.
         *
         * @param {object} options    The combo option array
         * @param {string} value      The target value
         * @returns {string}          The matched option text or undefined if not found
         */
        getComboOptionText: function (options, value) {
            var matchedOption = options.find(function (option) {
                return option.value === value;
            });
            return nfCommon.isDefinedAndNotNull(matchedOption) ? matchedOption.text : undefined;
        },

        /**
         * Creates a throttled function that invokes at most once every wait milliseconds.
         *
         * @param func                The function to throttle.
         * @param wait                The number of milliseconds to throttle invocations to.
         * @returns {function}        The throttled version of the function.
         */
        throttle: function (func, wait) {
            return _.throttle(func, wait);
        },

        /**
         * Find the corresponding value of the object key passed
         *
         * @param {object} obj        The obj to search
         * @param {string} key        The key path to return
         * @returns {object/literal}  The value of the key passed or undefined/null
         */
        getKeyValue : function(obj,key){
            return key.split('.').reduce(function(o,x){
                return(typeof o === undefined || o === null)? o : (typeof o[x] == 'function')?o[x]():o[x];
            }, obj);
        }

    };

    return nfCommon;
}));
