// (C) Copyright 2020 Hewlett-Packard Enterprise Company, L.P.

define(['fs/model/alerts/AlertResource',
    'fs/presenter/alerts/AlertsPresenter',
    'fs/view/common/DisplayListView',
    'hp/view/MasterPaneView',
    'hp/services/Log',
    'hp/core/LinkTargetBuilder',
    'hp/core/Notifications',
    'hp/core/Localizer',
    'hp/model/Session',
    'jquery',
    'lib/jquery.dataTables',
    'hp/lib/jquery.hpStatus',
    'hp/lib/jquery.hpTimestamp',
    'lib/jquery.dateFormat',
    'hp/lib/date',
    'hp/lib/jquery.hpDropMenu',
    'hp/lib/jquery.hpSelect',
    'hp/lib/jquery.hpSimpleSelect',
    'lib/jquery.ThreeDots'],
function (AlertResource, AlertsPresenter, displayListView, MasterPaneView, log,
        linkTargetBuilder, notifications, Localizer, session) {
"use strict";

    var AlertsBaseView = (function () {

        var DATE_FILTER = '#hp-alert-date-filter';
        var DATE_FROM = '#hp-alert-date-range-from';
        var DATE_TO = '#hp-alert-date-range-to';
        var SELECT_ALL = '.hp-header-select-all';
        var SELECTED = '.hp-alert.hp-selected';
        var RESTORE_ACTION = '#cic-alert-restore';
        var CLEAR_ACTION = '#cic-alert-clear';
        var DELETE_ACTION = '#cic-alert-delete';
        var ASSIGN_ACTION = '#cic-alert-assign';
        var DIALOG_TABLE = '#cic-displayitemlist-items-table';
        var DIALOG_LABEL = '#cic-displayitemlist-label';
        var ELLIPSIS_TEXT = '.ellipsis_text';
        var DIALOG_NOTIFY = '#cic-displayitemlist-details-notify';
        var DISPLAY_LIST_HEADER = '#cic-displayitemlist-header';
        var CLOSE_BUTTON = '#cic-displayitemlist-close-button';
        var CONFIRM_BUTTON = '#cic-displayitemlist-confirm-button';
        var HP_COMMENTS = '.hp-comments';
        var SINGLE_COMMENT = '.hp-comment';
        var HP_TIMESTAMP = '.hp-timestamp';
        var SHOW_COMMENTS = '.hp-show-hidden-comments';
        var ACTIONS = '#alerts-type-actions';
        var UNSEEN_DETAILS = ['resourceUri', 'activityUri', 'clearPriorEvents', 'PduTrapType',
            'lifeCycle', 'correctiveAction', 'cpqHoTrapFlags', 'cpqHoMibHealthStatusArray'];
        var LOCALIZED_DETAILS = ['SpecificTrap', 'GenericTrap', 'ipv4Address', 'sysName'];
        var EVENT_ROW_STYLING = "border-top:none; border-bottom:none; padding:10px 40px 0px 0px; "+
            "background:none; cursor:default;";
        var NOTES_MAXLENGTH = 1024;

        // values representing notification severity
        var NOTIFICATION_INFO = 'info';
        var NOTIFICATION_ERROR = 'error';
        /**
         * Constructor
         */
        function AlertsBaseView(tableId, globalView) {

            var resource = new AlertResource(globalView);
            var presenter = new AlertsPresenter(resource, globalView);
            var masterPaneView = new MasterPaneView();

            var detailsTemplate = null;
            var timerStopCount = 0;
            var expandedNotes = [];
            var users = [];
            var nameCache = [];

            var effectiveStatusColIndex = globalView ? 6 : 5;
            var effectiveAssignmentColIndex = globalView ? 8 : 7;
            var unassignedUser = Localizer.getString('fs.alerts.filter.unassigned').toLowerCase();
            var canUpdate;
            var canDelete;

            // private
            // resets the timerStopCount and retrieves the list
            // of alerts matching the current set of filters
            function getIndexResults() {
                presenter.getIndexResults();
            }

            // private
            // starts the refresh timer
            function startTimer() {
                timerStopCount--;
                if(timerStopCount < 0) {
                    timerStopCount = 0;
                }

                if(timerStopCount === 0) {
                    masterPaneView.enableUpdates();
                }
            }

            // private
            // stops the refresh timer
            function stopTimer() {
                timerStopCount++;
                masterPaneView.disableUpdates();
            }

            // private
            // resets the stop count to 0
            function onResetStopCount() {
                timerStopCount = 0;
            }

            // private
            // converts the passed in ISO8601 String to a viewable date
            function convertTime(dateVal) {
                var date = Date.parseISOString(dateVal);
                var formattedDate;
                if (date.isToday()) {
                    formattedDate = Localizer.getString('fs.alerts.date.today');
                } else if (date.getFullYear() === (new Date()).getFullYear()) {
                    formattedDate = $.format.date(date, 'MMM d');
                } else {
                    formattedDate = $.format.date(date, 'M/d/yy');
                }
                return '<div class="hp-timestamp">' +
                    formattedDate + ' ' +
                    $.format.date(Date.parseISOString(dateVal), 'h:mma') +
                    '</div>';
            }

            /**
             * Retrieves localized string given key.  If no string value, then returns keyEnding.
             * @param keyBase
             *      The initial portion of the resource key. For example "fs.alerts.category"
             * @param keyEnding
             *      The dynamic portion of the resource key. Most likely passed in
             *      as a dynamic value as part of an event object.
             * @param lowerCaseKeyEnding
             *      Boolean indicating whether the keyEnding
             *      should be lower cased before being used to retrieve the value
             *      associated with the key.
             */
            function getLocalizedString (keyBase, keyEnding, lowerCaseKeyEnding) {
                var localizedVal = null;
                var aKey = keyBase + (lowerCaseKeyEnding ? keyEnding.toLowerCase() : keyEnding);
                if (Localizer.hasValueForKey(aKey)) {
                    localizedVal = Localizer.getString(aKey);
                }
                return localizedVal ? localizedVal : keyEnding;
            }

            // private
            // adds a notification message to the queue
            function addNotification(message, statusVal) {
                var notificationObj = {
                    summary : message,
                    status : statusVal
                };
                notifications.add(notificationObj, true);
            }

            // private
            // deletes a single note
            function deleteNote(deleteLink) {
                var changeLogItem = $(deleteLink).parent(SINGLE_COMMENT);
                var alertRow = $($(deleteLink).closest('.hp-row-details-row.hp-selected')[0]).prev()[0];
                var alert = presenter.getAlertData($(alertRow).data('uri'));
                // remove the deleted note from the alert's changelog array
                var sortedChangeLog = alert.changeLog.sort(presenter.dateSort);
                var uri = sortedChangeLog[changeLogItem.index()-1].uri;

                var handlers = {
                    success : function (data) {
                        getIndexResults();
                        addNotification(Localizer.getString('fs.alerts.show.note_deleted'), NOTIFICATION_INFO);
                    },
                    error : function(errorInfo) {
                        // log the error
                        log.warn(errorInfo.errorMessage);
                        addNotification(Localizer.getString('fs.alerts.show.error_alerts_noteDeleted'), NOTIFICATION_ERROR);
                    }
                };

                presenter.deleteResourceByUri(uri, handlers);
            }

            // private
            // creates a table of event details
            function generateEventDetails(eventDetails) {
                // wrapper div for the table
                var details = $("<div></div>");
                // the table used to hold the event details
                var table = $("<table></table>");
                // templates used for creating each detail row
                var rowTemplate = $('<tr></tr>').attr('style', EVENT_ROW_STYLING);
                var cellTemplate = $('<td></td>').attr('style', EVENT_ROW_STYLING);
                var row;
                var description;
                var nonVarbindData = [];

                // iterate through each event detail and add it to the row
                $.each(eventDetails, function(index, detail) {
                    // check if the detail should be displayed or not
                    if($.inArray(detail.eventItemName, UNSEEN_DETAILS) < 0) {
                        // clone the template
                        row = rowTemplate.clone();
                        // check if the eventItemName should be localized
                        if($.inArray(detail.eventItemName, LOCALIZED_DETAILS) > -1) {
                            row.append(cellTemplate.clone().append(getLocalizedString(
                                'fs.alerts.eventData.', detail.eventItemName, false)));
                        } else if(detail.eventItemDescription && detail.eventItemDescription.length > 0) {
                            description = detail.eventItemDescription;
                            // if the description is > 80 chars, truncate the string at the next "."
                            if(description.length > 80) {
                                description = description.substring(0, description.indexOf('.', 80) + 1);
                            }
                            row.append(cellTemplate.clone().append(description));
                        } else {
                            row.append(cellTemplate.clone().append(detail.eventItemName));
                        }

                        if(detail.eventItemValue && detail.eventItemValue.length > 0) {
                            row.append(cellTemplate.clone().append(detail.eventItemValue));
                        } else {
                            row.append(cellTemplate.clone().append('&mdash;'));
                        }

                        // append the row to the table, always place the trap description on top
                        if(detail.eventItemName === "trapDescription") {
                            table.prepend(row);
                        } else if(! detail.isThisVarbindData) {
                            nonVarbindData.push(row);
                        } else {
                            table.append(row);
                        }
                    }
                });

                // append the nonVarbindData at the end
                $.each(nonVarbindData, function(index, row) {
                    table.append(row);
                });

                // set the styling for the wrapper div
                details.css('padding-left', $('th.hp-icon').outerWidth() + $('th.hp-event-date').outerWidth());
                details.css('cursor', 'default');
                // append the table in the wrapper div
                details.append(table);
                //return the details to the caller
                return details;
            }

            // private
            // retrieves all events associated with a given alert
            function getAssociatedEvents(alertUri, extraHandlers) {
                // get the associated event uris
                var eventUris = presenter.getAlertData(alertUri).associatedEventUris;
                // array holding the list of events returned
                var events = [];
                // counter used for determining the number of events retrieved
                var count = 0;

                var handlers = {success : function(data) {
                    // add the event to the array
                    events.push(data);
                    count++;
                    // check if we have gotten all the events
                    if(count === eventUris.length) {
                        extraHandlers.success(events);
                    }
                }, error : function(errorMsg) {
                    extraHandlers.error(errorMsg);
                }};

                // iterate through all of the event uris and get the event
                $.each(eventUris, function(index, currentUri) {
                    presenter.getEvent(currentUri, handlers);
                });
            }

            // private
            // shows a dialog view with the event list in it
            function showEventDetails(uri) {
                // the height and width of the dialog
                var dialogWidth = 700;
                var dialogHeight = 350;
                    displayListView.showDialog({
                        currentItemName : Localizer.getString('fs.alerts.eventData.alertDetails'),
                        type : "",
                        // used for displaying the alerts in the table
                        getItemsFunction : function(handlers) {
                            getAssociatedEvents(uri, handlers);
                        },
                        // called prior to backend request(s)
                        preDisplayFunction : function() {
                            stopTimer();
                            // set the close button text to "OK"
                            $(CLOSE_BUTTON).attr('value', Localizer.getString('fs.alerts.show.ok'));
                            // make the dialog box 700px wide
                        },
                        // called after backend request(s)
                        displayFunction : function() {
                            $('#cic-displayitemlist-section').css('margin','0px');
                            // set up the collapser actions
                            $('#cic-displayitemlist-items-table .hp-collapser').click(function(ev) {
                                var table = displayListView.getDataTable();
                                var eventRow = $(this).parents('tr')[0];

                                // if row is active close it, else display the details
                                if($(this).hasClass('hp-active')) {
                                    $(this).removeClass('hp-active');
                                    table.fnClose(eventRow);
                                } else {
                                    $(this).addClass('hp-active');
                                    var details = generateEventDetails(table.fnGetData(eventRow).eventDetails);
                                    table.fnOpen(eventRow, details[0], 'hp-event-details');
                                    details.show();
                                }
                            });
                            // expand the first event
                            $('#cic-displayitemlist-items-table .hp-collapser').first().click();
                        },
                        cleanupFunction : function() {
                            $('#cic-displayitemlist-items-table .hp-collapser').unbind('click');
                            startTimer();
                        },
                        // set the height and width of the dialog
                        sScrollY : dialogHeight,
                        sScrollX : dialogWidth,
                        // sort by the first column (date)
                        aaSorting: [[ 1, "desc" ]],
                        objectList: null,
                        columns : [{
                           // COLUMN 0: set expand/collapse icon
                           fnRender: function (oObj) {
                               return '<div class="hp-collapser"></div>';
                           },
                           sWidth : 20, sClass: "hp-icon", sDefaultContent : ''
                        },{
                            // COLUMN 1: created date
                            sTitle : Localizer.getString('fs.alerts.date.date'),
                            iDataSort : 3,
                            fnRender: function (oObj) {
                                return convertTime(oObj.aData.created);
                            },
                            sClass: "hp-event-date",
                            "mDataProp": "created"
                        },{
                            // COLUMN 2: event description
                            sTitle : "Event",
                            mDataProp : "description", sClass: "hp-event-desc"
                        },{
                            // COLUMN 3: set time sort column (always hidden, just used as sorting source)
                            fnRender : function (oObj) {
                                return oObj.aData.created;
                            },
                            bVisible: false,
                            sDefaultContent : ''
                        }],
                        dialog : {
                            modal: true,
                            // position middle of the page horizontally and 200px from the top
                            position : [($(window).width() / 2) - (dialogWidth / 2), 200],
                            draggable : true,
                            resizable : false,
                            width : dialogWidth
                        }
                    });
            }

            // private
            // appends a note the details
            // called when the details are generated (via generateAlertDetails()
            function appendNote(details, alertNote) {
                // copy the note template
                var note = $('.hp-comment-template.hp-template', details).clone();
                // remove the "hp-template" class
                note.removeClass('hp-template');
                note.removeClass('hp-comment-template');
                note.addClass('hp-comment');
                note.addClass('hp-comment-visible');
                // parse the date of the alertNote passed in
                var date = Date.parseISOString(alertNote.created);
                // set the user
                $('.hp-comment-user', note).text(alertNote.username);
                // set the note text
                $('.hp-comment-text', note).text(alertNote.notes);
                // determine if the date is today and format accordingly
                if (date.isToday()) {
                    $(HP_TIMESTAMP, note).html($.format.date(date, 'h:mma'));
                    $(HP_TIMESTAMP, note).append($('<span class="hp-date-annotate">&nbsp;(<span class="timeago" title="' +
                            alertNote.created + '"></span>)</span>'));
                    $(HP_TIMESTAMP + ' .timeago', note).timeago();
                }
                else if (date.getFullYear() === (new Date()).getFullYear()) {
                    $(HP_TIMESTAMP, note).html($.format.date(date, 'MMM d h:mma'));
                }
                else {
                    $(HP_TIMESTAMP, note).html($.format.date(date, 'M/d/yy h:mma'));
                }
                // add the note the DOM and display it
                note.show();
                $(HP_COMMENTS, details).append(note);

                // check if there are more than 5 notes
                if (note.index() > 5) {
                    var hiddenNote = $(SINGLE_COMMENT + '-visible', $(HP_COMMENTS, details)).first()
                                         .removeClass('hp-comment-visible').addClass('hp-comment-hidden');
                    var showLink = $(SHOW_COMMENTS, details);

                    // check if the show/hide notes links is displayed, if so and it's text is "View all n notes"
                    // then update the text and hide the oldest visible note. Do the same if the link is hidden
                    if ((showLink.is(':visible') && showLink.text() !== Localizer.getString('fs.alerts.show.show_five_notes')) ||
                        (showLink.is(':hidden'))) {
                            showLink.text(Localizer.getString('fs.alerts.show.view_all_notes',
                                [$(SINGLE_COMMENT, details).length])).show();
                            hiddenNote.hide();
                    }
                }

                // check if the note is user-entered and if it was added by the current user
                // if it meets both criteria, then display a link for that alert to be deleted
                if (!alertNote.userEntered || alertNote.username !== presenter.getCurrentUser()) {
                    $(SINGLE_COMMENT + '-delete', note).hide();
                }
                else {
                    $(SINGLE_COMMENT + '-delete', note).click(function () {
                        deleteNote(this);
                    });
                }
            }

            // private
            // called when the user adds a note
            function addNote(details, alertUri) {
                var handlers = {
                        success : function (data) {
                            getIndexResults();
                        },
                        error : function (errorInfo) {
                            // log the error
                            log.warn(errorInfo.errorMessage);
                            addNotification(Localizer.getString('fs.alerts.show.error_alerts_noteAdded'), NOTIFICATION_INFO);
                        }
                };

                // call the presenter to add the note
                presenter.addAlertNote(alertUri, $('.hp-comment-form-text', details).val(), handlers);
            }

         // private
            // It is called by keyup and paste handler of notes field to process data
            // in alerts notes field and display hp help message if characters reach
            // maxlength of notes field.
            function processNotesDataBasedOnMaxLength(notesField, hpHelpMsg, fromKeyup)
            {
                var text = notesField.val();
                var chars = text.length;
                if(fromKeyup)
                {
                    hpHelpMsg.toggle(chars > NOTES_MAXLENGTH);
                }
                else
                {
                    hpHelpMsg.toggle(chars >= NOTES_MAXLENGTH);
                }

                if(chars > NOTES_MAXLENGTH)
                {
                    notesField.val(text.substr(0, NOTES_MAXLENGTH));

                }
            }

            // private
            // used for generating the details of an alert when it is expanded
            function generateAlertDetails(alert) {
                // copy the details template
                var details = detailsTemplate.clone();
                // store the alert uri in the detail's data
                $(details).data('uri', alert.uri);
                // sort the changelog items of the alert
                var sortedChangeLog = alert.changeLog.sort(presenter.dateSort);
                // iterate through the sorted changelog items and append to the DOM
                $.each(sortedChangeLog, function (index, alertNote) {
                    appendNote(details, alertNote);
                });

                // add the resolution (if one exists)
                if(alert.correctiveAction) {
                    $('.hp-alert-resolution', details).html(Localizer.getString('fs.alerts.show.resolution') +
                        alert.correctiveAction);
                }

                var numberOfEvents;
                if(alert.associatedEventUris.length === 1) {
                    numberOfEvents = Localizer.getString('fs.alerts.show.based_on_event',
                        [alert.associatedEventUris.length]);
                } else {
                    numberOfEvents = Localizer.getString('fs.alerts.show.based_on_events',
                        [alert.associatedEventUris.length]);
                }


                // add the number of events the alert is based on
                $('.hp-alert-associated-events', details).html(numberOfEvents);

                $('.hp-help', details).hide();

                // set the handlers for add the new note (13 equals ENTER key)
                $('.hp-comment-form-text', details).bind('keydown', function (ev) {
                    if (13 === ev.keyCode) {
                        if ($('.hp-comment-add', details).is(':visible')) {
                            $('.hp-comment-add', details).click();
                        }
                        ev.preventDefault();
                    }
                });

             // check if the textarea is empty
                $('.hp-comment-form-text', details).bind('keyup click', function (ev) {
                    if ($('.hp-comment-form-text', details).val() === '') {
                        $('.hp-comment-add', details).fadeOut('200');
                    }
                    else if(13 !== ev.keyCode) {
                        $('.hp-comment-add', details).fadeIn('200');
                    }

                    processNotesDataBasedOnMaxLength(
                            $('.hp-comment-form-text', details),
                            $('.hp-help', details), true);

                });

                $('.hp-comment-form-text', details).bind('paste', function (ev) {
                        // use setTimeout to delay a little bit to let data paste
                        // into notes field before data is processed.
                        setTimeout(function(){
                            processNotesDataBasedOnMaxLength(
                                    $('.hp-comment-form-text', details),
                                    $('.hp-help', details), false);
                        }, 10);


                });


                $('.hp-alert-associated-events', details).bind('click', function(ev) {
                    showEventDetails($(details).data('uri'));
                });

                // set the button to add the new note
                $('.hp-comment-add', details).bind('click', function () {
                    addNote(details, alert.uri);
                    $('.hp-comment-add', details).fadeOut('200');
                });

                // shows/hides additional notes (if the alert has > 5 notes)
                $(SHOW_COMMENTS, details).bind('click', function() {
                   var uri = $(details).data('uri');
                   if ($(SHOW_COMMENTS, details).text() === Localizer.getString('fs.alerts.show.show_five_notes')) {
                       $(SHOW_COMMENTS, details).text(Localizer.getString('fs.alerts.show.view_all_notes',
                            [$(SINGLE_COMMENT, details).length]));
                       $(SINGLE_COMMENT + '-hidden', details).hide();
                       expandedNotes[uri] = false;
                   }
                   else {
                       $(SINGLE_COMMENT + '-hidden', details).show();
                       $(SHOW_COMMENTS, details).text(Localizer.getString('fs.alerts.show.show_five_notes'));
                       expandedNotes[uri] = true;
                   }
                });

                if(expandedNotes[alert.uri] === true) {
                    $(SHOW_COMMENTS, details).click();
                }
                // stop the timer when the alert is expanded
                stopTimer();

                var collapseAlert = function(ev) {
                    startTimer();
                    $(this).unbind('click', collapseAlert);
                };

                $('tr[data-resource-uri="' + alert.uri + '"] .hp-collapser').click(collapseAlert);

                return details;
            }


            // private
            // determines the notification message suffix to be used
            // when alerts are successfully updated/deleted
            function getNotificationMessage(presenterMethod, newValue) {
                var notificationMsg;

                // check what the new value is to determine what the
                // notification message should display
                if (newValue === 'Cleared') {
                    notificationMsg = "cleared";
                }
                else if (newValue === 'Active') {
                    notificationMsg = "restored";
                }
                else if (presenterMethod === presenter.assignUserToAlertByUri) {
                    // check if we are assigning or unassigning
                    if (newValue === null) {
                        notificationMsg = "unassigned";
                    }
                    else {
                        notificationMsg = "assigned";
                    }
                }
                else {
                  notificationMsg = "deleted";
                }

                return notificationMsg;
            }

            // private
            // called when an action if selected from the "Actions" menu or when
            // a single alert is cleared, restored, or assigned a user
            function editAlerts(uris, presenterMethod, newValue) {
                 // the total number of alerts processed
                 var alertsProcessed = 0;
                 // the total number of alerts that have been updated
                 var alertsChanged = 0;

                 // used for displaying in the notifications pane when the alerts
                 // are changed
                 var notificationMsg = getNotificationMessage(presenterMethod, newValue);

                 var handlers = {
                          success : function (data) {
                               // update the number of alerts processed
                               alertsProcessed++;

                               // if the alert was changed then increase the total number of alerts changed
                               // (no data is returned if the alert was not modified)
                               if (presenterMethod !== presenter.deleteResourceByUri) {
                                   if((data !== null)) {
                                       alertsChanged++;
                                   }
                               }
                               else {
                                    // if we are deleting then all "processed" alerts can be considered "changed"
                                    alertsChanged = alertsProcessed;
                               }


                               // check if all alerts selected have been processed
                               if (alertsProcessed === uris.length) {
                                    // determine whether to display "alert" or "alerts" in notification message
                                    if (alertsChanged === 1) {
                                         addNotification(alertsChanged + Localizer.getString(
                                             'fs.alerts.show.alert_' + notificationMsg, [newValue]), NOTIFICATION_INFO);
                                    } else if (alertsChanged === 0) {
                                        addNotification(Localizer.getString(
                                             'fs.alerts.show.no_alerts_' + notificationMsg, [newValue]), NOTIFICATION_INFO);
                                    }
                                    else {
                                         addNotification(alertsChanged + Localizer.getString(
                                             'fs.alerts.show.alerts_' + notificationMsg, [newValue]), NOTIFICATION_INFO);
                                    }

                                    // determine if anything changed, if so then update the table
                                    if(alertsChanged > 0) {
                                        getIndexResults();
                                    }
                               }
                          },
                          error : function (errorInfo) {
                               log.warn(errorInfo.errorMessage);
                               addNotification(Localizer.getString('fs.alerts.show.error_alerts_' +
                                   notificationMsg), NOTIFICATION_ERROR);
                          }
                 };

                 // iterate through the selected alerts and update them 1 by 1
                 // TODO update when the backend supports updating multiple alerts at a time
                 if (presenterMethod !== presenter.deleteResourceByUri) {
                     $.each(uris, function (index, currentUri) {
                        presenterMethod(currentUri, newValue, handlers);
                     });
                 }
                 else {
                     $.each(uris, function (index, currentUri) {
                        presenterMethod(currentUri, handlers);
                     });
                 }
            }

            // private
            // validates the input and calls the call the presenter/service
            function validateDateRange()
            {
                // simple regEx for matching: 1 or 2 digits followed by a "/" followed by 1 or 2 digits
                // followed by another "/" followed by 2 or 4 digits
                // Example of matching strings:
                // - 02/04/11
                // - 1/02/12
                // - 1/3/2012
                var regEx = /^^(\d{2}|[0-9]{1})\/(\d{2}|\d{1})\/(\d{4}|\d{2})$/;

                if ($(DATE_FROM).val().match(regEx) === null) {
                    $(DATE_FROM).addClass("hp-error");
                    return false;
                }

                // check if the to date matches the regEx
                if ($(DATE_TO).val().match(regEx) === null) {
                    $(DATE_TO).addClass("hp-error");
                    return false;
                }

                // check if the from date matches the regEx
                var fromVal = $(DATE_FROM).val();
                var toVal = $(DATE_TO).val();
                var fromDate = new Date(fromVal).getTime();
                var toDate = new Date(toVal).getTime();

                // check if fromDate is a number
                if (isNaN(fromDate)) {
                     $(DATE_FROM).addClass("hp-error");
                     return false;
                }

                // check if fromDate is a number
                if (isNaN(toDate)) {
                     $(DATE_TO).addClass("hp-error");
                     return false;
                }

                // check if fromDate is less than or equal to toDate
                if (fromDate <= toDate) {
                    $(DATE_FROM).removeClass("hp-error");
                    $(DATE_TO).removeClass("hp-error");
                    // update the filter
                    presenter.setDateRange(fromVal, toVal);

                    return true;
                }
                else {
                    $(DATE_FROM).addClass("hp-error");
                    $(DATE_TO).addClass("hp-error");

                    return false;
                }
            }

            // private
            // called when the selection changes
            function onSelectionChange(selection) {
                $('.hp-header-selection').html((selection.uris ? selection.uris.length : 0) + ' selected');
            }

            // private
            // called when the index results change
            function onIndexResultsChange(indexResults) {
                var newExpandedNotes = [];

                // sets alerts whose notes are expanded
                $.each(indexResults.members, function(index, result) {
                    if(expandedNotes[result.uri]) {
                        newExpandedNotes[result.uri] = true;
                    } else {
                        newExpandedNotes[result.uri] = false;
                    }
                });

                expandedNotes = newExpandedNotes;
            }

            // private
            // called when the user clicks the "Select All" link
            function selectAll() {
                var uris = [];
                var alerts = $('.hp-alert');
                $.each(alerts, function (index, result) {
                    uris.push($(result).data('resourceUri'));
                });
                presenter.selectAll(uris);
            }

            // private
            // hides the date pickers from the date text boxes
            function hideDatePickers(ev) {
                $('#hp-alert-date-range').removeClass('hp-date-clicked');
                $('#hp-alert-date-range-from').css('display', 'none');
                $('#hp-alert-date-range-to').css('display', 'none');
            }

            // private
            // shows the date pickers
            function showDatePickers(ev) {

                if(! $('#hp-alert-date-range').hasClass('hp-date-clicked')) {
                    $('#hp-alert-date-range').addClass('hp-date-clicked');
                    $(DATE_FROM).css('display', 'block');
                    $(DATE_TO).css('display', 'block');

                    $(DATE_FROM).click(function(ev) {
                        ev.stopPropagation();
                    });

                    $(DATE_FROM).datepicker({
                        onClose:function(data){
                           validateDateRange();
                        }
                    });

                    $(DATE_TO).click(function(ev) {
                        ev.stopPropagation();
                    });

                    $(DATE_TO).datepicker({
                       onClose:function(data){
                           validateDateRange();
                       }
                    });

                    $(DATE_FROM).val($.format.date(presenter.getDateOneMonthAgo().toString(), "M/dd/yyyy"));
                    $(DATE_TO).val($.format.date(new Date().toString(), "M/dd/yyyy"));
               }

                ev.stopPropagation();
            }


            // private
            // called when the date filter changes
            function onDateFilterChange(ev, value) {
                presenter.setDateFilter(value);
            }

            // private
            // called when any filter changes
            function onFilterChange(value) {
                // check if time is unset in the filters (the default)
                if(value && value.data && value.data.properties) {
                    if (value.data.properties.time === undefined || value.data.properties.time &&
                        value.data.properties.time.length === 0) {
                        $(DATE_FILTER).hpSelect('set', "");
                        $("#hp-activity-date-all").addClass('hp-selected');
                        $(DATE_FILTER + ' .hp-value').text(Localizer.getString('fs.alerts.date.allTime'));
                        hideDatePickers();
                    }
                }
            }


            // private
            // called when the page is first loaded and initializes the filters
            function initFilters() {
                $('.hp-alert-filter-reset').bind('click', function (ev) {
                    presenter.setDefaultFilters();
                });

                $(DATE_FILTER).hpSelect().change(onDateFilterChange);

                $('#hp-alert-date-range').bind('click',showDatePickers);

                $('.hp-alert-date-filter-option:not(#hp-alert-date-range)').bind('click',hideDatePickers);
            }

            // private
            // used for fetching the name of a resource
            function buildResourceNameFromUri(resourceUri, alertUri){
                presenter.getIndexForResource(resourceUri,{
                    success: function(resourceInfo){
                        if(resourceInfo.members.length === 0){
                            this.error();
                        } else {
                            nameCache[resourceUri] = resourceInfo.members[0].name;
                            // Set the name
                            $("tr[data-resource-uri='"+alertUri+"'] .hp-alert-source").html(
                            linkTargetBuilder.makeLink(resourceInfo.members[0].name, resourceUri, null, null));
                        }
                    },
                    error: function(){
                        // Couldn't get the name, use the URI
                        nameCache[resourceUri] = resourceUri;
                        $("tr[data-resource-uri='"+alertUri+"'] .hp-alert-source").html(
                            linkTargetBuilder.makeLink(resourceUri, resourceUri, null, null));
                    }
                });
            }


            // private
            // used for determining if alerts are currently visible
            function alertsExist() {
              if(presenter.getSelection().uris.length === 0) {
                return false;
              }
              return true;
            }

            // private
            // shows a dialog view with a list in it
            function showDisplayListView(selectedCount, displayFunction, cleanupFunction, headerText) {
                    displayListView.showDialog({
                        currentItemName : headerText,
                        type : "",
                        // used for displaying the alerts in the table
                        getItemsFunction : function(handlers) {
                           var items = [];

                           // iterate through each selected alert and get the information needed to form the table
                           // in the dialog popup.  The index of the columns depends on whether we want to show alert
                           // source or not
                           $.each($(SELECTED), function (index, current) {
                               var data = presenter.getAlertData($(current).data('uri'));
                               var columns = $('td', current);
                               items[index] = {"date" : columns[3].innerHTML, "source" : columns[4].innerHTML,
                                    "severity" : columns[1].innerHTML,
                                    "alert" : columns[2].innerHTML,
                                    "severityVal" : data.severity, "createdVal" : data.created};
                           });

                           handlers.success(items);
                        },
                        // used for appending DOM elements to the dialog
                        displayFunction : displayFunction,
                        // used for cleaning up the added DOM elements when the dialog is closed
                        cleanupFunction : cleanupFunction,
                        // checks to see if there is more than one alert selected, if so make it collapsible and display the count
                        message : (selectedCount === 1 ? null :
                            selectedCount + Localizer.getString('fs.alerts.show.selected_alerts')),
                        collapsible : (selectedCount === 1 ? false : true),
                        hideTitleBar : (headerText ? false : true),
                        sScrollY : (selectedCount > 1 ? "150px" : "50px"),
                        sScrollX : "550",
                        aaSorting: [[ 0, "desc" ]],
                        objectList : null,
                        columns : [{
                            // COLUMN 0 Date
                            "sTitle" : Localizer.getString('fs.alerts.date.date'),
                            "mDataProp" : "date",
                            "sWidth" : "15%",
                            "iDataSort" : (globalView ? 5 : 4)
                        },{
                            // COLUMN 1: Source (only shown in global view)
                            "sTitle" : Localizer.getString('fs.alerts.show.source'),
                            "mDataProp" : "source",
                            "sWidth" : "20%",
                            "sClass" : "display-list-view-source",
                            "bVisible" : globalView // hide the source column if context-sensitive
                        },{
                            // COLUMN 2: Severity
                            "sTitle" : "<div class='hp-status hp-status-unknown'></div>",
                            "mDataProp" : "severity",
                            "sWidth" : "5%",
                            "sClass" : "hp-icon",
                            "iDataSort" : (globalView ? 4 : 3)
                        },{
                            // COLUMN 3: Description
                            "sTitle" : Localizer.getString('fs.alerts.show.alert'),
                            "mDataProp" : function(oObj) {
                                return '<div><span class="ellipsis_text">'+ oObj.alert +'</span></div>';
                            },
                            "sWidth" : "60%"
                        },{
                            // COLUMN 4: set status sort column (always hidden, just used as sorting source)
                             "mDataProp" : function (oObj) {
                                 var sortValues = {Unknown : 0, OK : 1, Warning : 2, Disabled : 3, Critical : 4};
                                 return sortValues[oObj.severityVal];
                             },
                             "bVisible": false
                        },{
                            // COLUMN 5: set time sort column (always hidden, just used as sorting source)
                            "mDataProp" : function (oObj) {
                                return oObj.createdVal;
                            },
                            "bVisible": false
                        }],
                        dialog : {
                            modal:true,
                            position : "center",
                            draggable : true,
                            resizable : false,
                            width : '600px'
                        }
                    });

                    // truncate alert description to be one line
                    $(ELLIPSIS_TEXT, DIALOG_TABLE).parent().ThreeDots({max_rows: 1});

                    // bind ThreeDots to be updated when the dropdown is selected the first time
                    // (without this the line is truncated to one letter regardless the width of the column i.e. "T...")
                    $(DIALOG_LABEL).one('click', function() {
                        $(ELLIPSIS_TEXT, DIALOG_TABLE).parent().ThreeDots({max_rows: 1});
                    });
            }

            // register single alertState change event
            function onAlertStateChangeAction(ev) {
                var value;
                var alertData = presenter.getAlertData($($(ev.currentTarget).parents('tr')[0]).data('uri'));
                if (alertData.alertState === 'Active') {
                    value = 'Cleared';
                } else {
                    value = 'Active';
                }
                editAlerts([alertData.uri], presenter.setAlertState, value);
            }

            // set up change in alert assignment events
            function onAlertAssignmentAction(ev, value) {
                var alert = presenter.getAlertData($($(ev.currentTarget).parents('tr')[0]).data('uri'));
                // check if user equals "unassigned"
                if (value === Localizer.getString('fs.alerts.filter.unassigned').toLowerCase()) {
                    value = null;
                }
                editAlerts([alert.uri], presenter.assignUserToAlertByUri, value);
            }

            // private
            // unbinds all actions in the "Actions" menu
            function unbindActions() {
                $(SELECT_ALL).unbind();
                $(CLEAR_ACTION).unbind();
                $(RESTORE_ACTION).unbind();
                $(DELETE_ACTION).unbind();
                $(ASSIGN_ACTION).unbind();

                $(tableId).off('focusin', '.cic-alerts-assignment', stopTimer);
                $(tableId).off('focusout', '.cic-alerts-assignment', startTimer);
                $(tableId).off('change', '.cic-alerts-assignment', onAlertAssignmentAction);
                $(tableId).off('click', '.hp-alert-state-change', onAlertStateChangeAction);
            }

            // private
            // used for setting up the events that occur
            // when the user selects an option from the "Actions" menu
            function initActions() {
                $('#alerts-type-actions').hpDropMenu();

                // inits the "Select All" link
                $(SELECT_ALL).click(selectAll);

                // inits the clear action
                $(CLEAR_ACTION).click(function () {
                    if(alertsExist()) {
                        editAlerts(presenter.getSelection().uris, presenter.setAlertState, 'Cleared');
                    }

                });

                // inits the restore actions
                $(RESTORE_ACTION).click(function () {
                    if(alertsExist()) {
                        editAlerts(presenter.getSelection().uris, presenter.setAlertState, 'Active');
                    }
                });

                // inits the delete actions
                $(DELETE_ACTION).click(function () {
                    if(alertsExist()) {
                        stopTimer();
                        var selectedCount = presenter.getSelection().uris.length;

                        var displayFunction = function() {

                            var deleteMsg = Localizer.getString('fs.alerts.delete.confirm_single');
                            if (selectedCount > 1) {
                                deleteMsg = Localizer.getString('fs.alerts.delete.confirm_multiple');
                            }

                            // show "Delete selected alerts?"
                            $(DIALOG_NOTIFY).after(
                                '<div id="cic-displayitemlist-header">'+ deleteMsg +'</div>');
                            // add confirm button
                            $(CLOSE_BUTTON).before('<input id="cic-displayitemlist-confirm-button"' +
                                'class="ui-button"type="button" value="' + Localizer.getString('fs.alerts.delete.ok') +
                                '" />');

                            // set the close button text to "Cancel"
                            $(CLOSE_BUTTON).attr('value', Localizer.getString('fs.alerts.list.cancel'));

                            $(CONFIRM_BUTTON).click(function() {
                                // delete the alerts
                                editAlerts(presenter.getSelection().uris, presenter.deleteResourceByUri, null);
                                // close the dialog
                                $(CLOSE_BUTTON).click();
                            });
                        };

                        var cleanupFunction = function() {
                            startTimer();
                            $(DISPLAY_LIST_HEADER).remove();
                            $(CONFIRM_BUTTON).remove();
                        };

                        var headerText = (selectedCount === 1 ? Localizer.getString('fs.alerts.delete.delete_title_singular') :
                            Localizer.getString('fs.alerts.delete.delete_title_plural') );

                        showDisplayListView(selectedCount, displayFunction, cleanupFunction, headerText);
                    }
                });

                $(tableId).on('focusin', '.cic-alerts-assignment', stopTimer);
                $(tableId).on('focusout', '.cic-alerts-assignment', startTimer);
                $(tableId).on('change', '.cic-alerts-assignment', onAlertAssignmentAction);
                $(tableId).on('click', '.hp-alert-state-change', onAlertStateChangeAction);

                // inits the assign action
                $(ASSIGN_ACTION).click(function () {
                  if(alertsExist()) {
                        stopTimer();
                        var selectedCount = presenter.getSelection().uris.length;
                        var displayFunction = function() {
                            // append "Assign alerts to: "
                            $(DIALOG_NOTIFY).after(
                                '<div id="cic-displayitemlist-header"><span>' + Localizer.getString(
                                'fs.alerts.show.assignAlertsTo') + '</span></div>');
                            var assignDropdown = $('<div id="cic-displaylistitem-assign"></div>');
                            assignDropdown.css('display', 'inline');

                            var user = unassignedUser;
                            if (selectedCount >= 1) {
                                var uris = presenter.getSelection().uris;
                                user = presenter.getAlertData(uris[0]).assignedToUser;
                                for (var i = 1; i < selectedCount; ++i) {
                                    var tempUser = presenter.getAlertData(uris[i]).assignedToUser;
                                    if (user != tempUser) {
                                        user = unassignedUser;
                                        break;
                                    }
                                }
                            }

                            assignDropdown.hpSelect({options: users, multiSelect: false});
                            assignDropdown.hpSelect('set', (user && users.hasOwnProperty(user)) ? user : unassignedUser);

                            // append the dropdown
                            $(DISPLAY_LIST_HEADER + ' span').after(assignDropdown);

                            $('#cic-displaylistitem-assign .hp-value').css('display', 'inline');

                            // add confirm button
                            $(CLOSE_BUTTON).before('<input id="cic-displayitemlist-confirm-button"' +
                                ' class="ui-button" type="button" value="' + Localizer.getString('fs.alerts.show.assignAlerts') +
                                '" />');

                            // set the close button text to "Cancel"
                            $(CLOSE_BUTTON).attr('value', Localizer.getString('fs.alerts.list.cancel'));

                            $(CONFIRM_BUTTON).click(function() {
                                // set the previously selected alert
                                //setPrevAlertUri();
                                // get the selected value
                                var user = $('#cic-displaylistitem-assign .hp-value').text();
                                // check if user equals "unassigned"
                                if(user === unassignedUser) {
                                   user = null;
                                }
                                // update multiple alerts with the selected user
                                editAlerts(presenter.getSelection().uris, presenter.assignUserToAlertByUri, user);
                                // close the dialog
                                $(CLOSE_BUTTON).click();
                            });
                        };

                        var cleanupFunction = function() {
                           startTimer();
                           $(DISPLAY_LIST_HEADER).remove();
                           $(CONFIRM_BUTTON).remove();
                       };

                       var headerText = (selectedCount === 1 ? Localizer.getString('fs.alerts.assign.assign_title_singular') :
                           Localizer.getString('fs.alerts.assign.assign_title_plural') );

                       showDisplayListView(selectedCount, displayFunction, cleanupFunction, headerText);
                    }
                });
            }

            //private
            // This is the render function for COLUMN 0
            // Using named function to prevent memory leak
            function fnExpandCollapseRender(oObj) {
                return '<div class="hp-collapser"></div>';
            }

            //private
            // This is the render function for COLUMN 1
            // Using named function to prevent memory leak
            function fnSeverityRender(oObj) {
                var severity = presenter.getStatus(oObj.aData.severity);
                return '<div class="hp-status hp-status-' + severity + '"><span class="hp-value">' + severity + '</span></div>';
            }

            //private
            // This is the render function for COLUMN 2
            // Using named function to prevent memory leak
            function fnDescriptionRender(oObj) {
                return linkTargetBuilder.replaceTokensWithLinks(oObj.aData.description);
            }

            //private
            // This is the render function for COLUMN 3
            // Using named function to prevent memory leak
            function fnTimeRender(oObj) {
                return convertTime(oObj.aData.created);
            }

            //private
            // This is the render function for COLUMN 4
            // Using named function to prevent memory leak.
            // This function was updated to use associatedResource to get
            //  resourceName or resourceUri. If resourceName is null or not
            //  defined, resourceUri is used instead.
            function fnSourceRender(oObj) {
                if(oObj.aData.resourceUri != null && nameCache[oObj.aData.resourceUri]) {
                    return "<span class='hp-alert-source'>" +
                        linkTargetBuilder.makeLink(nameCache[oObj.aData.resourceUri],
                            oObj.aData.resourceUri, null, null) + "</span>";
                }
                else if(oObj.aData.associatedResource.hasOwnProperty("resourceName")
                        && oObj.aData.associatedResource.resourceName !== null
                        && oObj.aData.associatedResource.resourceName.length !== 0)
                {
                    var resourceName = oObj.aData.associatedResource.resourceName;
                    nameCache[oObj.aData.associatedResource.resourceUri] = resourceName;
                    return "<span class='hp-alert-source'>" +
                        linkTargetBuilder.makeLink(
                        resourceName,
                        oObj.aData.associatedResource.resourceUri, null, null) + "</span>";
                }
                else
                {
                    // get the id of the alert and populate the source asynchronously
                    buildResourceNameFromUri(oObj.aData.resourceUri, oObj.aData.uri);
                    return "<span class='hp-alert-source'></span>";
                }


            }

            //private
            // This is the render function for COLUMN 5
            // Using named function to prevent memory leak
            function fnCategoryRender(oObj) {
                return getLocalizedString('fs.alerts.category.', oObj.aData.healthCategory, true);
            }

            //private
            // This is the render function for COLUMN 6
            // Using named function to prevent memory leak
            function fnStateRender(oObj) {
                if(canUpdate){
                    return '<div class="hp-reveal-control">' +
                    '<span class="hp-value">' + getLocalizedString('fs.alerts.filter.', oObj.aData.alertState, true) + '</span>' +
                    '<a class="hp-alert-state-change hp-control">' +
                    ('Active' === oObj.aData.alertState ? Localizer.getString('fs.alerts.show.clear') :
                    Localizer.getString('fs.alerts.show.restore')) +
                    '</a>';
                }
                else {
                    return '<span class="hp-value">' +
                        getLocalizedString('fs.alerts.filter.', oObj.aData.alertState, true) +
                        '</span>';
                }
            }

            //private
            // This is the render function for COLUMN 7
            // Using named function to prevent memory leak
            function fnNotesRender(oObj) {
                return oObj.aData.changeLog.length;
            }

            //private
            // This is the render function for COLUMN 8
            // Using named function to prevent memory leak
            function fnUserRender(oObj) {
                if(canUpdate){
                    return '<div class="cic-alerts-assignment"></div>';
                }
                else{
                    return oObj.aData.assignedToUser;
                }
            }

            //private
            // called after each row is rendered.
            // Using named function to prevent memory leak
            function rowCallback(nRow, aData, iDisplayIndex, iDisplayIndexFull) {
                $('td:eq(' + effectiveStatusColIndex + ') div.hp-status', nRow).hpStatus();

                var user = presenter.getAlertData(aData.uri).assignedToUser;
                var userAssignment = $('td:eq(' + effectiveAssignmentColIndex + ') div.cic-alerts-assignment', nRow);
                userAssignment.hpSelect({ options: users, multiSelect: false });
                userAssignment.hpSelect('set', (user && users.hasOwnProperty(user)) ? user : unassignedUser);

                var $nRow = $(nRow);
                $nRow.attr("data-resource-uri", aData.uri);
                $nRow.data('uri', aData.uri);
                $nRow.addClass('hp-alert');

                 return nRow;
            }

            //private
            // Called for each row in the table before its cleared, removes all hp-select event tags
            // Using named function to prevent memory leak
            function clearRowCallback(nRow) {
                $('td:eq(' + effectiveAssignmentColIndex + ') div.cic-alerts-assignment', nRow).hpSelect('destroy');
                return nRow;
            }

            // private
            // called at startup to initiate the alerts table
            function initTable() {
                detailsTemplate = $('#hp-alert-details-template').remove().attr('id', '');
                if(!canUpdate) {
                    $('.hp-comment-form' , detailsTemplate).remove();
                }
                var columnsArray = [{
                    // COLUMN 0: set expand/collapse icon
                    fnRender: fnExpandCollapseRender,
                    sWidth: 20,
                    sClass: "hp-icon",
                    sDefaultContent: ""
                },{
                    // COLUMN 1: set status
                    fnRender: fnSeverityRender,
                    sWidth: 20,
                    sClass: "hp-icon",
                    "mDataProp": "severity"
                },{
                    // COLUMN 2: set description
                    fnRender: fnDescriptionRender,
                    "mDataProp": "description"
                },{
                    // COLUMN 3: set date/time
                    fnRender: fnTimeRender,
                    sWidth: 10,
                    "mDataProp": "created"
                },{
                    // COLUMN 4: set source (may be hidden for context-sensitive lists)
                    fnRender: fnSourceRender,
                    "bVisible": globalView, // TODO this screws up sorting
                    sWidth: 80,
                    "mDataProp": "resourceUri"
                },{
                    // COLUMN 5: set category
                    fnRender: fnCategoryRender,
                    "mDataProp": "healthCategory"
                },{
                    // COLUMN 6: set state
                    fnRender: fnStateRender,
                    sWidth: 5,
                    "mDataProp": "alertState"
                },{
                    // COLUMN 7: set note count
                    fnRender: fnNotesRender,
                    bUseRendered: "false",
                    bSortable : false, // TODO figure out how to sort on note count
                    sWidth: 20,
                    sDefaultContent: ""
                },{
                    // COLUMN 8: set assignment
                    fnRender: fnUserRender,
                    sWidth: 5,
                    "mDataProp": "assignedToUser"
                }];

                var masterPaneViewInitArgs = {
                    resource: resource,
                    routePrefix: globalView ? '/alert' : null,
                    pane : (globalView ? $('.hp-master-full') :
                        $('#hp-alert-pane .hp-details-contents')),
                    page : (globalView ? $('#hp-alert-page') : $('#hp-alert-pane')),
                    contextSensitive : !globalView,
                    table: $(tableId),
                    multiSelect: true,
                    dataTableOptions:  {
                        aoColumns : columnsArray,
                        aaSorting : [[ 3, "desc" ]],
                        fnRowCallback : rowCallback,
                        fnClearRowCallback : clearRowCallback
                    },
                    detailsRenderer: generateAlertDetails
                }
                masterPaneView.init(masterPaneViewInitArgs);
            }

            // public
            this.setPhysicalResourceUri = function(uri)
            {
                presenter.setResourceUri(uri);
            };

            // private
            // called when page is first loaded to get the
            // list of users to be displayed
            function getAllUsers(){
               users = [];
               presenter.getAllUsers({
                  success : function (returnedUsers) {
                    users = returnedUsers;
                    // add "no one" to the list
                    users[Localizer.getString('fs.alerts.filter.unassigned').toLowerCase()] = Localizer.getString(
                        'fs.alerts.filter.unassigned').toLowerCase();
                  },
                  error : function (errorInfo) {
                      // caller was not authorized to get the list of users
                      // make the list just be the currentUser and "no one"
                      users.push(presenter.getCurrentUser());
                      users.push(Localizer.getString('fs.alerts.filter.unassigned').toLowerCase());
                  }
              });
            }

            /**
             * @public
             */
            this.pause = function () {
                expandedNotes = [];
                presenter.off('indexResultsChange', onIndexResultsChange);
                presenter.off('selectionChange', onSelectionChange);
                presenter.off('filterChange', onFilterChange);
                presenter.off('resetStopCount', onResetStopCount);
                unbindActions();
                nameCache = [];
                presenter.pause();
                masterPaneView.pause();
            };

            this.resume = function () {
                presenter.on('indexResultsChange', onIndexResultsChange);
                presenter.on('selectionChange', onSelectionChange);
                presenter.on('filterChange', onFilterChange);
                presenter.on('resetStopCount', onResetStopCount);
                initActions();
                presenter.resume();
                masterPaneView.resume();
            };

            this.init = function() {
                $('#hp-alerts').attr('id', tableId.substring(1));
                canUpdate = session.canPerformAction('alerts', 'Update');
                canDelete = session.canPerformAction('alerts', 'Delete');
                getAllUsers();
                initTable();
                initFilters();
                displayListView.init();
                presenter.init();

                $(ASSIGN_ACTION).toggle(canUpdate);
                $(CLEAR_ACTION).toggle(canUpdate);
                $(RESTORE_ACTION).toggle(canUpdate);
                $(DELETE_ACTION).toggle(canDelete);
                $(ACTIONS).toggle(canDelete || canUpdate);

                this.resume();
            };
        }

        return AlertsBaseView;

    }());

    return AlertsBaseView;
});
