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

        /**
         * Gets an access token from the specified url.
         *
         * @param accessTokenUrl    The access token
         * @returns the access token as a deferred
         */
        getAccessToken: function (accessTokenUrl) {
            return $.Deferred(function (deferred) {
                if (nfStorage.hasItem('jwt')) {
                    $.ajax({
                        type: 'POST',
                        url: accessTokenUrl
                    }).done(function (token) {
                        deferred.resolve(token);
                    }).fail(function () {
                        deferred.reject();
                    })
                } else {
                    deferred.resolve('');
                }
            }).promise();
        },

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