/**
 * Definition of the AlertList object that defines the methods and attributes relevant
 * to managing the alert list page.
 */

/*global AjaxUtils, AlertsConnector, DWRHelper, JSON, SearchPane, URLBuilder, Utf8, YAHOO, document, getNextSibling, getPreviousSibling, onclick_alert, window */

// The constructor for the AlertList object
function AlertList(userId)
{
    // The id of the user that is editing the alerts
    this.userId = userId;

    // The id of the alert currently being edited
    this.selectedAlertId = null;

    // The name of the alert currenlty being edited
    this.selectedAlertName = null;

    // The tabView control that contains the alert information
    this.tabView = null;

    // The action that should be performed when the form is submitted
    this.formAction = "";

    // a function that is called after an alert is saved
    this.afterSaveFunction = null;

    // The list of AlertPaginator objects for each set of alerts results
    this.alertPaginators = [];

    // Sets the instance of the alert list here
    AlertList.instance = this;

    // Create a new instance of the form change tracker
    this.formChangeTracker = new FormChangeTracker();
    this.formChangeTracker.addListener(this);
}

// The following are strings that are defined in the messages_en.properties file
AlertList.alertCreationSuccess = "<<<uninitialized>>>";
AlertList.alertUpdateSuccess = "<<<uninitialized>>>";
AlertList.deleteAlertQuery = "<<<uninitialized>>>";
AlertList.createAlertPrompt = "<<<uninitialized>>>";
AlertList.newAlertName = "<<<uninitialized>>>";
AlertList.promptForDelete = "<<<uninitialized>>>";
AlertList.renameBeforeSave = "<<<uninitialized>>>";
AlertList.loadingEle = "<<<uninitialized>>>";
AlertList.onlyNumeric = "<<<uninitialized>>>";
AlertList.nameRequired = "<<<uninitialized>>>";
AlertList.nameAlreadyExists = "<<<uninitialized>>>";
AlertList.alertNotValid = "<<<uninitialized>>>";
AlertList.saveAlertComplete = "<<<uninitialized>>>";
AlertList.errorSaving = "<<<uninitialized>>>";
AlertList.followingErrors = "<<<uninitialized>>>";
AlertList.errorField = "<<<uninitialized>>>";
AlertList.errorText = "<<<uninitialized>>>";
AlertList.btnCancel = "<<<uninitialized>>>";
AlertList.btnCont = "<<<uninitialized>>>";
AlertList.btnSaveCont = "<<<uninitialized>>>";
AlertList.btnSaveChanges = "<<<uninitialized>>>";
AlertList.btnDel = "<<<uninitialized>>>";
AlertList.btnDelAlert = "<<<uninitialized>>>";
AlertList.month1 = "<<<uninitialized>>>";
AlertList.month2 = "<<<uninitialized>>>";
AlertList.month3 = "<<<uninitialized>>>";
AlertList.month4 = "<<<uninitialized>>>";
AlertList.month5 = "<<<uninitialized>>>";
AlertList.month6 = "<<<uninitialized>>>";
AlertList.month7 = "<<<uninitialized>>>";
AlertList.month8 = "<<<uninitialized>>>";
AlertList.month9 = "<<<uninitialized>>>";
AlertList.month10 = "<<<uninitialized>>>";
AlertList.month11 = "<<<uninitialized>>>";
AlertList.month12 = "<<<uninitialized>>>";
AlertList.html1 = "<<<uninitialized>>>";
AlertList.html2 = "<<<uninitialized>>>";
AlertList.html3 = "<<<uninitialized>>>";


//The labels used for the alert tabs
AlertList.alertDetailsLabel = "<<<uninitialized>>>";
AlertList.alertDetailsDirtyLabel = "<<<uninitialized>>>";

// The temporary name that an alert created from a serch will have.
// NB: This string is never seen by the user.  It is used to force the alert
// to appear at the top of the list
AlertList.alertFromSearchName = "<<<uninitialized>>>";

// The id that a new alert will have before it is saved on the server
AlertList.newAlertId = "<<<uninitialized>>>";

// The instance of the alert list object that was created and is being used on the
// alerts.jsp page
AlertList.instance = null;

/**
 * Handles ajax errors that occur on this page
 * @param methodName the name of the method that failed
 * @param message the message from the exception that was thrown
 * @param info furhter information on the exception that was thrown.
 */
AlertList.pageErrorHandler = function(methodName, message, info)
{
    // if the user is no longer logged in
    if (info.javaClassName == "com.deepwebtech.coral.user.UserNotLoggedInException")
    {
        window.location.reload();
    }
    else
    {
        DWRHelper.displayDWRError(methodName, message, info);
    }
};

/**
 * function called following the update of the session preferences
 * @param prefs the new preferences object
 */
AlertList.onUpdatePreferences = function(prefs)
{
    if (prefs.resultsPerPage != Paginator.resultsPerPage)
    {
        Paginator.resultsPerPage = prefs.resultsPerPage;
    }
};


/**
 * Initiates a selectAlert command by requesting data from the server
 * @param alertId the id of the alert that was selected
 */
AlertList.prototype.selectAlert = function(alertId)
{
    // if this is the same alert id, don't do anything
    if (alertId == this.selectedAlertId)
    {
        return;
    }

    var afterFunc = function(alertId)
    {
        return function()
        {
            AlertsConnector.retrieveAlert(alertId, AlertList.retrieveAlertCallbackObject);
        };
    }(alertId);
    this.promptForDeleteOfUnsavedAlert(afterFunc);
};

/**
 * Deletes the element in the alert list that corresponds to an unsaved new alert.
 */
AlertList.discardNewAlert = function()
{
    var alertEle = document.getElementById(AlertList.newAlertId);
    alertEle.parentNode.removeChild(alertEle);

    AlertList.instance.setClean();
};

/**
 * Sets the dirty flag to false in the formChangeTracker
 */
AlertList.prototype.setClean = function()
{
    // Clear the dirty flag in the form change tracker
    if (this.formChangeTracker)
    {
        this.formChangeTracker.setClean();
    }
};

/**
 * Shows the tabview and hides the No Alerts screen
 */
AlertList.prototype.showTabs = function()
{
    var alertTabs = document.getElementById("alertTabs");
    var noAlertsDiv = document.getElementById("noAlertsDiv");

    alertTabs.style.display = "";
    noAlertsDiv.style.display = "none";
};

/**
 * Hides the tabview and shows the No Alerts screen
 */
AlertList.prototype.hideTabs = function()
{
    var alertTabs = document.getElementById("alertTabs");
    var noAlertsDiv = document.getElementById("noAlertsDiv");

    alertTabs.style.display = "none";
    noAlertsDiv.style.display = "";
};

/**
 * Prompts the user to let them know that they are about to lose their unsaved alert
 * @return true if it is ok to proceed with the operation.
 */
AlertList.prototype.promptForDeleteOfUnsavedAlert = function(afterFunc)
{
    var buttons;
    var text;

    // if an unsaved new alert is selected, prompt the user to save the alert
    if (this.selectedAlertId && this.selectedAlertId == AlertList.newAlertId)
    {
        buttons =
        [
            { text: AlertList.btnCancel, isDefault:true },
            { text: AlertList.btnCont, handler: function(afterFunc)
            {
                return function()
                {
                    AlertList.discardNewAlert();
                    afterFunc();
                };
            }(afterFunc) },

            { text: AlertList.btnSaveCont, handler: function(afterFunc)
            {
                return function()
                {
                    AlertList.instance.afterSaveFunction = afterFunc;
                    AlertList.instance.saveAlert();
                };
            }(afterFunc)}
        ];

        text = AlertList.promptForDelete;
    }
    else if (this.formChangeTracker && this.formChangeTracker.isDirty())
    {
        buttons =
        [
            { text: AlertList.btnCancel, isDefault:true },
            { text: AlertList.btnCont, handler: function(afterFunc)
            {
                return function()
                {
                    afterFunc();
                };
            }(afterFunc) },

            { text: AlertList.btnSaveCont, handler: function(afterFunc)
            {
                return function()
                {
                    AlertList.instance.afterSaveFunction = afterFunc;
                    AlertList.instance.saveAlert();
                };
            }(afterFunc)}
        ];

        text = AlertList.unsavedAlertWarning;
    }

    if (typeof(text) != "undefined")
    {
        MessageBox.displayDialog(AlertList.btnSaveChanges, text, buttons);
    }
    else
    {
        afterFunc();
    }
};

/**
 * Selects the given alert from the data retrieved from the server
 * @param data the alert summary object
 */
AlertList.prototype._selectAlert = function(alertSummary)
{
    this.selectAlertElement(alertSummary.alert.alertId);

    this.selectedAlertName = alertSummary.alert.alertName;

    // Load the alert into the tabView
    this.addAlertToTabView(alertSummary);
};

/**
 * Selects the element with the give id and de-selects the previous element
 * @param alertId the id of the element to select
 */
AlertList.prototype.selectAlertElement = function(alertId)
{
    if (this.selectedAlertId !== null)
    {
        var selectedAlert = document.getElementById(this.selectedAlertId);
        if (selectedAlert)
        {
            selectedAlert.className = "alertDiv";
        }
    }

    this.selectedAlertId = alertId;

    var newSelectedAlert = document.getElementById(this.selectedAlertId);
    newSelectedAlert.className = "selectedAlertDiv";
};

/**
 * The callback from the call to retrieveAlert
 * @param data the alertSummary for the given alert
 */
AlertList.retrieveAlert_callback = function(data)
{
    AlertList.instance._selectAlert(data);
};

/**
 * The error handler from the call to retrieveAlert
 * @param message The error message
 * @param info The additional information, which includes the stack trace
 * from the call
 */
AlertList.retrieveAlert_errorHandler = function(message, info)
{
    AlertList.pageErrorHandler("AlertList.retrieveAlert", message, info);
};


/**
 * Actually does the deletion
 * @param alertId the id of the alert to delete.
 */
AlertList.doDeleteAlert = function(alertId)
{
    if (alertId == AlertList.newAlertId)
    {
        AlertList.instance.setClean();
        AlertList.instance._deleteAlert(alertId);
    }
    else
    {
        AlertsConnector.deleteAlert(alertId, AlertList.deleteAlertCallbackObject);
    }
};

/**
 * Initiates a deleteAlert command by requesting data from the server
 * @param alertId the id of the alert that was selected
 */
AlertList.prototype.deleteAlert = function(alertId)
{
    var buttons = [ { text: AlertList.btnCancel, isDefault:true },
        { text: AlertList.btnDel, handler: function(alertId)
        {
            return function()
            {
                AlertList.doDeleteAlert(alertId);
            };
        }(alertId) }
    ];

    MessageBox.displayDialog(AlertList.btnDelAlert, AlertList.deleteAlertQuery, buttons);
};

/**
 * Deletes the given alert
 * @param data the alert id
 */
AlertList.prototype._deleteAlert = function(alertId)
{
    // Get the HTML element for this alert
    var ele = document.getElementById(alertId);

    var newSelection = CoralUtils.getNextSibling(ele);
    if (newSelection === null)
    {
        newSelection = CoralUtils.getPreviousSibling(ele);
    }

    ele.parentNode.removeChild(ele);

    // if this is the selected alert
    if (this.selectedAlertId == alertId)
    {
        if (this.selectedAlertId == AlertList.newAlertId)
        {
            this.selectedAlertId = null;
        }

        if (newSelection !== null)
        {
            // Select the next alert
            this.selectAlert(newSelection.id);
        }

        // Set the selected alert id to null
        this.selectedAlertId = null;

        // Remove the tabs from the tab view
        this._clearTabView();
    }

    this.mediator();
};

/**
 * The callback from the call to deleteAlert
 * @param data the alertSummary for the given alert
 */
AlertList.deleteAlert_callback = function(data)
{
    AlertList.instance._deleteAlert(data);
};

/**
 * The error handler from the call to deleteAlert
 * @param message The error message
 * @param info The additional information, which includes the stack trace
 * from the call
 */
AlertList.deleteAlert_errorHandler = function(message, info)
{
    AlertList.pageErrorHandler("AlertList.deleteAlert", message, info);
};

/**
 * Determines if the alert name already exists.  Alert names are unique for
 * each user.  Since strata does a case independent comparison, it will be done
 * here as well.
 * @param alertName the name of the alert to check
 * @return true if it exists
 */
AlertList.prototype.alertNameExists = function(alertName, alertId)
{
    var compareAlertName = alertName.toLowerCase();

    var alertListEle = document.getElementById("innerAlertList");

    // Loop through all sub elements of the alertList
    var alertNameExists = false;
    var alertElements = alertListEle.getElementsByTagName("div");
    for (var i = 0; i < alertElements.length && !alertNameExists; ++i)
    {
        alertNameExists = (this.getAlertBaseName(alertElements[i].innerHTML.toLowerCase()) == compareAlertName);
        if (alertNameExists && alertId && alertId == alertElements[i].id)
        {
            alertNameExists = false;
        }
    }

    return alertNameExists;
};

/**
 * Create a new, unsaved alert, with a unique name.
 */
AlertList.prototype.createUniqueAlert = function()
{
    var alertName = AlertList.newAlertName;
    var i = 2;

    while (AlertList.instance.alertNameExists(alertName))
    {
        alertName = AlertList.newAlertName + " " + i.toString();
        ++i;
    }

    AlertList.instance._createAlert(AlertList.newAlertId, alertName);
};

/**
 * Initiates a createAlert command by creating an unsaved alert on the client.
 */
AlertList.prototype.createAlert = function()
{
    this.promptForDeleteOfUnsavedAlert(this.createUniqueAlert);
};

/**
 * Clears all of the tabs from the tabview
 */
AlertList.prototype._clearTabView = function()
{
    while (this.tabView.getTab(0))
    {
        this.tabView.removeTab(this.tabView.getTab(0));
    }
};

/**
 * Creates an element in the alert list
 * @param alertId the id of the element
 * @param alertName the text of the element
 */
AlertList.prototype.createAlertElement = function(alertId, alertName)
{
    // replace < and > with &lt; and &gt;
    var escapedAlertName = "";
    for (i = 0; i < alertName.length; ++i)
    {
        if (alertName.charAt(i) == ">")
        {
            escapedAlertName += "&gt;";
        }
        else if (alertName.charAt(i) == "<")
        {
            escapedAlertName += "&lt;";
        }
        else
        {
            escapedAlertName += alertName.charAt(i);
        }
    }

    // Create the element that will be addded to the alert list
    var ele = document.createElement("div");
    ele.id = alertId;
    ele.innerHTML = escapedAlertName;
    ele.className = "alertDiv";
    ele.onclick = function()
    {
        return onclick_alert(alertId);
    };

    return ele;
};

/**
 * Creates an alert from a previously run search
 * @param ssid the search session id, used to get the previous search
 */
AlertList.prototype.createAlertFromSearch = function(ssid)
{
    this._createAlert(AlertList.newAlertId, AlertList.alertFromSearchName, ssid);
};

/**
 * Creates an empty alert
 * @param alertId the id of the alert
 * @param alertName the name of the alert
 * @param ssid the ssid of the search to create an alert from
 */
AlertList.prototype._createAlert = function(alertId, alertName, ssid)
{
    var ele = this.createAlertElement(alertId, alertName);

    this._insertElementIntoAlertList(ele, alertName);

    this.selectAlertElement(alertId);

    // Load the alert into the tabView
    this.addAlertToTabView(null, alertId, alertName, ssid);

    this.mediator();
};

/**
 * Retrieves the real name of the alert by removing the alert count.
 * @param alertName the name of the alert as displayed in the alert list.
 */
AlertList.prototype.getAlertBaseName = function(alertName)
{
    var ret = alertName;
    var pos = alertName.indexOf("&nbsp;&nbsp;[");
    if (pos != -1)
    {
        ret = alertName.substring(0, pos);
    }
    return ret;
};

/**
 * Inserts an element into the alert list
 * @param ele the element to insert
 * @param alertName the name of the alert that is getting inserted.
 */
AlertList.prototype._insertElementIntoAlertList = function(ele, alertName)
{
    var compareAlertName = this.getAlertBaseName(alertName.toLowerCase());

    var alertListEle = document.getElementById("innerAlertList");

    // Loop through all sub elements of the alertList
    var insertBeforeElement = null;
    var alertElements = alertListEle.getElementsByTagName("div");
    for (var i = 0; i < alertElements.length && insertBeforeElement === null; ++i)
    {
        if (compareAlertName < this.getAlertBaseName(alertElements[i].innerHTML.toLowerCase()))
        {
            insertBeforeElement = alertElements[i];
        }
    }

    if (insertBeforeElement === null)
    {
        alertListEle.appendChild(ele);
    }
    else
    {
        alertListEle.insertBefore(ele, insertBeforeElement);
    }
};

/**
 * Checks to see if the tab got an error when its data was retrieved.
 */
AlertList.prototype.checkForRetrievalError = function()
{
    var errorDiv = document.getElementById("exceptionViewError");
    if (errorDiv && errorDiv.innerHTML == "UserNotLoggedInException")
    {
        window.location.reload();
    }
};

/**
 * This method attaches a FormChangeTracker object to the instance of the AlertList object.
 * @param isNewAlert true if this is a new alert.
 */
AlertList.prototype.initEditView = function(isNewAlert)
{
    this.checkForRetrievalError();

    AlertList.instance.formChangeTracker.attachEventHandlers("search");

    g_collectionTreeManager.setCategories(document.getElementById("catz").innerHTML.split(","));
    g_collectionTreeManager.setInitialCollections(document.getElementById("initialCollections_ele").innerHTML.split(","));
    g_collectionTreeManager.setupCategoryTree();

    // If the alert is getting set from a search, set the name in the list to be
    // the name that is returned in the edit form.
    var selectedAlertElement = document.getElementById(AlertList.instance.selectedAlertId);
    if (selectedAlertElement.innerHTML == AlertList.alertFromSearchName)
    {
        selectedAlertElement.innerHTML = document.getElementById("alertName").value;
    }

    // if this is a new alert, mark the form as dirty
    if (isNewAlert)
    {
        AlertList.instance.formChangeTracker.setDirty();
    }
};

/**
 * Fired by the FormChangeTracker whenever the dirty flag of the form changes.
 * @param isDirty true if the form is dirty
 */
AlertList.prototype.onDirtyChanged = function(isDirty)
{
    var editAlertTab = this.tabView.getTab(0);
    if (typeof editAlertTab == "undefined")
    {
        return;
    }

    var label;
    if (isDirty)
    {
        label = AlertList.alertDetailsDirtyLabel;
    }
    else
    {
        label = AlertList.alertDetailsLabel;
    }

    editAlertTab.set("label", label, true);

    if (document.getElementById("saveAlert"))
    {
        document.getElementById("saveAlert").disabled = !isDirty;
    }
};

/**
 * Creates the title that will be used on the alert list
 * @param alertName the name of the alert
 * @param count the number of results in the first tab
 * @return a title for the alert in the list
 */
AlertList.prototype.createAlertListTitle = function(alertName, count)
{
    return alertName + "&nbsp;&nbsp;[" + count + "]";
};

/**
 * adds the alerts info into the tab view
 * @param alertSummary the data to add the tab view
 */
AlertList.prototype.addAlertToTabView = function(alertSummary, alertId, alertName, ssid)
{
    // Clear the dirty flag in the form change tracker
    this.setClean();

    // Clear the paginators array
    this.alertPaginators = [];
    this.alertPaginators[0] = null;

    if (alertSummary)
    {
        alertId = alertSummary.alert.alertId;
        alertName = alertSummary.alert.alertName;
    }

    var loadingEle = AlertList.loadingEle;

    // Remove the tabs from the tab view
    this._clearTabView();

    // Build the url that will be used to retrieve the alert form
    var urlBuilder = new URLBuilder("alerts/alerts-form-generator.html");
    urlBuilder.addParam("userId", this.userId);
    urlBuilder.addParam("alertId", alertId);
    urlBuilder.addParam("alertName", alertName);

    if (ssid)
    {
        urlBuilder.addParam("ssid", ssid);
    }

    var isDetailsActive = (!alertSummary) || (alertSummary.alertCounts.searchIds.length === 0);

    // Add the form for entering the alerts data into the first tab
    var editAlertTab = new YAHOO.widget.Tab({
        label: AlertList.alertDetailsLabel,
        content: loadingEle,
        dataSrc: urlBuilder.toString(),
        cacheData: true,
        active: isDetailsActive});

    // Use a closure to create the content change handler.  Here, we pass in a flag indicating
    // whether or not this is a new alert.
    var contentChangeHander = function(isNewAlert)
    {
        return function()
        {
            AlertList.instance.initEditView(isNewAlert);
        };
    }(alertId == AlertList.newAlertId);

    editAlertTab.addListener('contentChange', contentChangeHander);

    this.tabView.addTab(editAlertTab);

    // Loop on the result counts
    if (alertSummary && alertSummary.alertCounts)
    {
        // Regenerate the name of the alert in the list to reflect then number of counts in the
        // first tab
        if (alertSummary.alertCounts.counts.length > 0)
        {
            var ele = document.getElementById(alertId);
            ele.innerHTML = this.createAlertListTitle(alertName, alertSummary.alertCounts.counts[0]);
        }

        for (var i = 0; i < alertSummary.alertCounts.searchIds.length; ++i)
        {
            var resultTab = new YAHOO.widget.Tab({
                label: this.getResultTabLabel(alertSummary.alertCounts.runDates[i], alertSummary.alertCounts.counts[i]),
                content: loadingEle,
                dataSrc: "alerts/alerts-results-retriever.html?userId=" + this.userId + "&alertId=" + alertSummary.alert.alertId + "&searchId=" + alertSummary.alertCounts.searchIds[i],
                cacheData: true,
                active: (i === 0)
            });

            resultTab.addListener('contentChange', this.initResultsView,
                {counts: alertSummary.alertCounts.counts[i],
                 searchId: alertSummary.alertCounts.searchIds[i],
                 alertId: alertId,
                 tabIndex: i+1}
                    );

            this.tabView.addTab(resultTab);
        }
    }
};

/**
 * Initializes the result view.  Equivalent to an onload event
 * @param eventInfo the Yahoo event - specific data
 * @param initObj the data that is passed from the tab creation
 */
AlertList.prototype.initResultsView = function(eventInfo, initObj)
{
    var inst = AlertList.instance;
    inst.checkForRetrievalError();
    inst.createPaginator(initObj);
};

/**
 * Creates a new instance of the alerts paginator if the active tab has been selected.
 * @param initObj  the data that is passed from the tab creation
 */
AlertList.prototype.createPaginator = function(initObj)
{
    var activeTabIndex = this.tabView.getTabIndex(this.tabView.get("activeTab"));

    if (initObj.tabIndex == activeTabIndex)
    {
        this.alertPaginators[initObj.tabIndex] = new AlertsPaginator(initObj.searchId, initObj.alertId, initObj.counts);
        this.alertPaginators[initObj.tabIndex].resultCount = (initObj.counts < Paginator.resultsPerPage) ? initObj.counts : Paginator.resultsPerPage;
        this.alertPaginators[initObj.tabIndex].paginate();
    }
};

/**
 * Builds the label for the alert results tab
 * @param rundate the date the alert was run on
 * @param counts the number of results returned on that run date
 * @return a string for use as the label of a result tab
 */
AlertList.prototype.getResultTabLabel = function(rundate, counts)
{
    var months = [AlertList.month1,
                AlertList.month2,
                AlertList.month3,
                AlertList.month4,
                AlertList.month5,
                AlertList.month6,
                AlertList.month7,
                AlertList.month8,
                AlertList.month9,
                AlertList.month10,
                AlertList.month11,
                AlertList.month12];

    var date = new Date();
    var dates = rundate.split("-");
    date.setFullYear(dates[0]);
    date.setMonth(dates[1] - 1);
    date.setDate(dates[2]);

    return "<b>" + months[date.getMonth()] + "&nbsp;" + date.getDate() + "</b>" + "&nbsp;&nbsp;[" + counts + "]";
};

/**
 * Sets the action to perform when the form is submitted
 * @param event the event object
 */
AlertList.prototype.setFormAction = function(event)
{
    if (typeof(event.target) == "undefined")
    {
        event.target = event.srcElement;
    }

    this.formAction = event.target.id;
};

/**
 * Does a form submittal
 */
AlertList.prototype.submitAlert = function()
{
    if (this.formAction == "saveAlert")
    {
        return this.saveAlert();
    }
    else
    {
        return this.testAlert();
    }
};

/**
 * Saves the alert
 */
AlertList.prototype.saveAlert = function()
{
    var form = document.getElementById("search");
    if (this.alertIsValid())
    {
        AjaxUtils.postFormData("alerts/save-alert.html", form, AlertList.saveAlert_callback);
    }

    return false;
};

/**
 * Validate the alert for all required data.
 */
AlertList.prototype.alertIsValid = function()
{
    var form = document.getElementById("search");
    var isValid = false;
    var text = "";
    var alertName = document.getElementById("alertName").value;

    if (SearchPane.instance.validateAdvancedSearch(form, false))
    {
        if (ValidationUtils.isBlank(alertName))
        {
            text = AlertList.nameRequired;
            document.getElementById("alertName").focus();
        }
        else if (this.alertNameExists(alertName, document.getElementById("alertId").value))
        {
            text = AlertList.nameAlreadyExists;
            document.getElementById("alertName").focus();
        }
        else
        {
            isValid = true;
        }
    }
    else
    {
        text = SearchPane.instance.errorString;
    }

    if (!isValid)
    {
        MessageBox.error(AlertList.alertNotValid, text);

        // Cancel any pending action by clearing the after save function.
        this.afterSaveFunction = null;
    }

    return isValid;
};

/**
 * This method is called to test the alert that the user has generated.
 */
AlertList.prototype.testAlert = function()
{
    var form = document.getElementById("search");
    var ret = false;

    if (this.alertIsValid())
    {
        form.target = "_blank";
        form.action = "search.html";
        ret = true;
    }

    return ret;
};

/**
 * Replace the new alert id in the link's href with the actual alert id
 * @param eleId the id of the element
 * @param newAlertId the new alert id.
 */
AlertList.prototype.updateFeedLink = function(eleId, newAlertId)
{
    document.getElementById(eleId).href =
    document.getElementById(eleId).href.replace(AlertList.newAlertId, newAlertId);
};

/**
 * The callback method that receieves the response from saving the alert
 * @param req the XMLHttpRequestObject
 */
AlertList.prototype._saveAlert = function(req)
{
    var displayText = req.responseText;

    var isError = false;

    if (displayText.indexOf("SUCCESS") != -1)
    {
        var saveAlertResponse = JSON.parse(req.responseText);
        var alertName = this.createAlertListTitle(Utf8.decode(saveAlertResponse.alertName), 0);

        // if this is a new alert
        if (saveAlertResponse.isNewAlert == "true")
        {
            displayText = AlertList.alertCreationSuccess;

            // Get the element with the id of AlertList.newAlertId
            var oldElement = document.getElementById(AlertList.newAlertId);
            var parentNode = oldElement.parentNode;
            var newElement = this.createAlertElement(saveAlertResponse.alertId, alertName);

            // Delete the old element
            parentNode.removeChild(oldElement);

            // Insert the new element into the alert list
            this._insertElementIntoAlertList(newElement, alertName);

            // Give the alertId field the new value of the id
            document.getElementById("alertId").value = saveAlertResponse.alertId;

            this.selectAlertElement(saveAlertResponse.alertId);

            // Show the feed links
            this.updateFeedLink("rss_feed", saveAlertResponse.encryptedAlertId);
            this.updateFeedLink("atom_feed", saveAlertResponse.encryptedAlertId);
            document.getElementById("feedSpan").style.display = "";
        }
        else
        {
            displayText = AlertList.alertUpdateSuccess;

            // Set the name in the alert list, in case it changed.
            var selectedEle = document.getElementById(saveAlertResponse.alertId);
            selectedEle.innerHTML = alertName;

            // Remove the child from the alertList and then reinsert it.
            selectedEle = selectedEle.parentNode.removeChild(selectedEle);
            this._insertElementIntoAlertList(selectedEle, alertName);
        }

        this.setClean();

        this.selectAlert(saveAlertResponse.alertId);
    }
    else
    {
        isError = true;

        try
        {
            var errorObject = JSON.parse(req.responseText);
            displayText = AlertList.followingErrors;
            displayText += "<br/><br/>";

            if (errorObject.errors)
            {
                for (var i = 0; i < errorObject.errors.length; ++i)
                {
                    displayText += AlertList.html1;
                    displayText += AlertList.errorField + errorObject.errors[i].field;
                    displayText += AlertList.html2;
                    displayText += AlertList.errorText + errorObject.errors[i].message;
                    displayText += AlertList.html3;
                }
            }
            else if (errorObject.status)
            {
                displayText += errorObject.status;
            }
        }
        catch(e)
        {
            // Data is not a json package
        }
    }

    if (isError)
    {
        if (displayText.indexOf("UserNotLoggedInException") >= 0)
        {
            window.location.reload();
        }

        else
        {
            MessageBox.error(AlertList.errorSaving, displayText);
        }
    }
    else
    {
        MessageBox.info(AlertList.saveAlertComplete, displayText);
    }

    if (AlertList.instance.afterSaveFunction)
    {
        AlertList.instance.afterSaveFunction();
        AlertList.instance.afterSaveFunction = null;
    }
};

/**
 * The callback method that receieves the response from saving the alert
 * @param req the XMLHttpRequestObject
 */
AlertList.saveAlert_callback = function(req)
{
    AlertList.instance._saveAlert(req);
};

/**
 * Implements the mediator pattern for the ui.  It enables or
 * disables the UI elements based on the state of the data.
 */
AlertList.prototype.mediator = function()
{
    // Get the number of child nodes in in the innerAlertList
    var innerAlertList = document.getElementById("innerAlertList");
    var alerts = innerAlertList.getElementsByTagName("div");

    // Enable or disable the deleteAlert button
    document.getElementById("deleteAlert").disabled = (alerts.length === 0);

    if (alerts.length === 0)
    {
        this.hideTabs();
    }
    else
    {
        this.showTabs();
    }
};

/**
 * The object used when making calls to deleteAlert
 */
AlertList.deleteAlertCallbackObject = {
    callback:     AlertList.deleteAlert_callback,
    timeout:      DWRHelper.ajaxTimeout,
    errorHandler: AlertList.deleteAlert_errorHandler
};

/**
 * The object used when making calls to retrieveAlert
 */
AlertList.retrieveAlertCallbackObject = {
    callback:     AlertList.retrieveAlert_callback,
    timeout:      DWRHelper.ajaxTimeout,
    errorHandler: AlertList.retrieveAlert_errorHandler
};

//-----------------------------------------------------------------------------
// The following methods support pagination
//-----------------------------------------------------------------------------

/**
 * Gets the alertPaginator object associated with the current tab.
 */
AlertList.prototype.getActivePaginator = function()
{
    var tabIndex = this.tabView.getTabIndex(this.tabView.get("activeTab"));
    return this.alertPaginators[tabIndex];
};

/**
 * Shows the first set of results
 */
AlertList.prototype.showFirst = function()
{
    return this.getActivePaginator().showFirst();
};

/**
 * Shows the previous set of results
 */
AlertList.prototype.showPrevious = function()
{
    return this.getActivePaginator().showPrevious();
};

/**
 * Shows the next set of results
 */
AlertList.prototype.showNext = function()
{
    return this.getActivePaginator().showNext();
};

/**
 * Shows the final set of results
 */
AlertList.prototype.showLast = function()
{
    return this.getActivePaginator().showLast();
};

/**
 * Goes to a page of results with the given start position
 * @param startPos the position in the
 */
AlertList.prototype.goToPage = function(startPos)
{
    return this.getActivePaginator().gotoPage(startPos);
};

