/* plopez- changed ResultList.getResultsDWRObject = timeout:      30000, */
/**
 * Definition of the ResultList object that defines the methods and attributes relevant
 * to managing the result list page.
 */
/*globals ClusterPane, CollectionStatusPanel, DWRHelper, DWRUtil, Paginator, ResultListConnector, URLBuilder, getImageDir, YAHOO */
/*jslint forin:true, undef:true, widget:true, browser:true */
function ResultList(ssid, tabCount, selTab, refreshMode, searchId, displayMoreResultsDialog, filters)
{
    // Set the instance
    ResultList.instance = this;

    // The globally unique ID for the current search session.
    this.ssid = ssid;

    // The id of the current search
    this.searchId = searchId;

    // The number of tabs that will be displayed
    this.tabCount = tabCount;

    // The index to the currently selected tab
    this.currentTabIndex = selTab;

    // Whether to prompt the user to refresh results or not at end of search.
    this.refreshMode = refreshMode;

    // The array of result panes that will be displayed
    this.resultPanes = [];

    // The array of cluster panes that will be displayed
    this.clusterPanes = [];

    // The most current search status object.
    this.resultListStatus = null;

    // The sum of all displayable results from all containers w/o any collection limits.
    this.displayTotal = 0;

    // The number of milliseconds to wait for getResultListStatus requests.
    this.statusTimeout = 1000;

    // The list of filters applied to the current view.
    this.filters = filters;

    // The list of the panes that are currently active in each tab.  This
    // is used to display the pane when the tabs are switched.
    this.activeTabPanes = [];

    // The current number of marked results.
    this.markedCount = 0;

    this.markListUrl     = "markList.html";
    this.emailResultsUrl = "resultsEmailer.html";

    // The currently selected tab
    this.selectedTab = null;

    // The container of the currently selected tab
    this.selectedContainer = null;

    //the YUI search-popup-window element
    this.searchPopup = null;

    // The number of milliseconds to wait for getCollectionStatus requests.
    this.statusTimeout = 2000;

    // True if the more results dialog should be displayed when search is finished
    this.displayMoreResultsDialog = displayMoreResultsDialog;

    // Set when the state of a selected cluster needs to be restored.
    this.clusterInitialState = null;

    // The Configurable List of fields to run through the spell checker
    this.spellSuggestFieldsList = [];
}

/**
 * This is a reference to the single instance of the resultList object
 */
ResultList.instance = null;

// The text that will be displayed on the search popup window
ResultList.searchPopupButton1Text = "<<<uninitialized>>>";
ResultList.searchPopupButton2Text = "<<<uninitialized>>>";
ResultList.spellFieldSummary = "<<uninitialized>>";
ResultList.spellFieldSnippet = "<<uninitialized>>";

// The module name that will be used in the yahoo ui history manager
ResultList.moduleName = "ResultList";

/**
 * Returns the curently active result pane object
 */
ResultList.prototype.getActivePane = function()
{
    return this.activeTabPanes[this.currentTabIndex];
};

/**
 * Post constructor call to intialize AJAX calls to update the resultListStatus and collectionStatus.
 * Should be called after all other attributes have been initialized and you
 * are ready to start actively polling for status.
 */
ResultList.prototype.init = function()
{
    this.createSearchPopup();

    this.initPage();

    // Poll the server to get the status of the search
    this.getResultSearchStatus(this.ssid, this.filters, 0);
};

/**
 * Initializes the clusterPane objects by adding the resultList class as
 * a listener for events fired from the cluster pane.
 */
ResultList.prototype.initClusterPanes = function()
{
    var i;

    for (i = 0; i < this.clusterPanes.length; ++i)
    {
        this.clusterPanes[i].addListener(this);
    }
};

/**
 * Perform any task related to a search status update.  This method will always be
 * called after the resultListStatus object has been updated via AJAX.
 */
ResultList.prototype.updateSearchStatus = function()
{
    // if there aren't any results for the active pane,
    if (this.getActivePane().displayCount === 0 && this.resultListStatus.paneCounts[this.currentTabIndex] > 0)
    {
        // If this is a reloadiing of a cluster, first get the clusters.
        if (this.clusterInitialState)
        {
            // Get the clusters for this pane
            this.clusterPanes[this.currentTabIndex].getClusters(this.ssid, this.isInActiveTab(this.currentTabIndex),
                                                     this.resultListStatus.paneCounts[this.currentTabIndex], this.isSearchFinished(),
                                                     this.filters);
        }
        else
        {
            // Get the results for the visible pane
            this.showPage(-1, true);
        }
    }

    this.updateSearchProgress();

    this.updateResultCounts();
};

/**
 * Setup the Page with onclick handlers for the tabs and select the appropriate
 * tab to display initially based on the resultPane value.
 */
ResultList.prototype.initPage = function()
{
    this.getSpellingSuggestion();

    this.initClusterPanes();

    for (var i = 0; i < this.tabCount; ++i)
    {
        // Initialize the activePanes array with the top level pane
        this.activeTabPanes[i] = this.resultPanes[i];
    }

    this.getInitialState();

    YAHOO.util.History.onReady(
        function ()
        {
            var state = ResultList.instance.getCurrentState();
            ResultList.instance.switchTabs(state.currentTabIndex, state);
        }
    );

    YAHOO.util.History.initialize("yui-history-field", "yui-history-iframe");
};

/**
 * Sets the local resultListStatus attribute to the new value. Calls updateSearchStatus
 * to allow any additional updates to be made.  If the search is not finished, issues
 * the next AJAX request to refresh the resultListStatus.
 * @param resultListStatus the current status of the search
 */
ResultList.prototype.setResultListStatus = function(resultListStatus)
{
    this.resultListStatus = resultListStatus;

    // Update any displayed information about the search
    this.updateSearchStatus();

    // if search is finished...
    if (this.isSearchFinished())
    {
        this.handleSearchFinished();
    }
    else
    {
        this.getResultSearchStatus(this.ssid, this.filters, this.statusTimeout);
    }
};

/**
 * Returns the total filtered results as the sum of the paneCounts for each pane
 */
ResultList.prototype.getTotalFilteredResults = function()
{
    var totalFilteredResults = 0;
    for (var i in this.resultListStatus.paneCounts)
    {
        totalFilteredResults += this.resultListStatus.paneCounts[i];
    }

    return totalFilteredResults;
};

/**
 * Tests whether search is finished.
 * @return true if search is finished
 */
ResultList.prototype.isSearchFinished = function()
{
    if (this.resultListStatus === null)
    {
        return false;
    }
    else
    {
        return this.resultListStatus.searchFinished;
    }
};

/**
 * Retrieve the current state of the search using an AJAX call.
 * @param ssid
 * @param filters
 * @param timeout
 */
ResultList.prototype.getResultSearchStatus = function(ssid, filters, timeout)
{
    window.setTimeout(function(){ResultListConnector.getResultSearchStatus(ssid, filters, ResultList.getResultSearchStatusDWRObject);}, timeout);
};

/**
 * Callback function to the method ResultListConnector.getResultSearchStatus
 * @param resultSearchStatus the resultSearchStatus object
 */
ResultList.getResultSearchStatus_callback = function(resultSearchStatus)
{

    //set the reslutListStatus
    ResultList.instance.setResultListStatus(resultSearchStatus.resultListStatus);

    // if there is a collection status panel configured
    if (document.getElementById("collectionStatusPanel"))
    {
        CollectionStatusPanel.setCollectionStatus(resultSearchStatus.collectionStatus);
    }
};


/**
 * Callback function to the method ResultListConnector.getResultSearchStatus
 * @param data the data received from the AJAX call.
 */
ResultList.getResultSearchStatus_errorHandler = function(message, info)
{
    DWRHelper.displayDWRError("ResultList.getResultStatus_errorHandler", message, info);
};

/**
 * The object used when making calls to ResultListConnector.getResultSearchStatus
 */
ResultList.getResultSearchStatusDWRObject = {
  callback:     ResultList.getResultSearchStatus_callback,
  errorHandler: ResultList.getResultSearchStatus_errorHandler
};

/**
 * Reload the current page at a new starting result location, and refreshing
 * the result snapshot, if needed
 * @param newStart the start position in the result list to display
 * @param refresh true if a new snapshot should be generated.
 */
ResultList.prototype.showPage = function(newStart, refresh)
{
    if (newStart == -1)
    {
        newStart = this.getActivePane().startPosition;
    }
    this.getActivePane().getPageOfResults(newStart, refresh, this.ssid, this.filters);
};

/**
 * Adds all of the outstanding results to the displayed page by first setting
 * each pane's displayCount to 0 and then refreshing the currently displayed page
 */
ResultList.prototype.addResults = function()
{
    // Loop through all of the top level panes and set their display count to 0
    // This will ensure that they will get reloaded the next time that their tab is clicked.
    for (var i = 0; i < this.tabCount; ++i)
    {
        this.resultPanes[i].displayCount = 0;
        this.resultPanes[i].resultCount  = 0;
        this.resultPanes[i].resetSelectedCollection();
        this.updateResultCounter(i);
    }

    // if the selected pane is a cluster pane, select its corresponding top level pane
    // so that the results and clusters can get updated
    if (this.getActivePane().paneId >= this.tabCount)
    {
        this.activeTabPanes[this.currentTabIndex] = this.resultPanes[this.getActivePane().paneId - this.tabCount];
    }

    // Refresh the active pane
    this.showPage(0, true);

    if (this.isSearchFinished())
    {
        // Hide the result count indicator
        document.getElementById("more-results-info").style.visibility = "hidden";
    }
};

/**
 * Reorders the results on the page by changing the ordering parameter and re-reading
 * the results.
 * @param orderBy the means in which to order the results
 */
ResultList.prototype.reorderResults = function(orderBy)
{
    // Set the ordering in the active pane and then re-get the results
    this.getActivePane().resultSortField = orderBy;
    this.showPage(0, false);
};

/**
 * Emails the current result listing.
 */
ResultList.prototype.emailResults = function()
{
    if(this.getActivePane().displayCount > 0)
    {
        var urlBuilder = new URLBuilder(this.emailResultsUrl);
        urlBuilder.addParam("ssid", this.ssid);
        urlBuilder.addParam("resultPane", this.currentTabIndex);
        urlBuilder.addParam("snapshotIndex", this.getActivePane().paneId);
        urlBuilder.addParam("resultSortField", this.getActivePane().resultSortField);
        urlBuilder.addParam("collectionId", this.getActivePane().selectedCollection);

        var win = window.open(urlBuilder.toString(), null,"top=270,left=250,height=517,width=628,status=yes,toolbar=no,menubar=no,location=no,scrollbars=no,resizable=yes");
        win.focus();
    }
    else
    {
        window.alert("You must have results in order to send an email");
    }
};


/**
 * View results in the current snap shot only from the given collectionId
 * @param collectionId the collecion to get results for
 */
ResultList.prototype.viewCollection = function(collectionId)
{
    this.getActivePane().setSelectedCollection(collectionId);
    this.showPage(0, false);
};

//------------------------------------------------------------------------------
// Functions for paging through the list of results
//------------------------------------------------------------------------------

/**
 * Gets the page of results from the current pane starting at newStart
 */
ResultList.prototype.gotoPage = function(newStart)
{
    this.getActivePane().gotoPage(newStart, this.ssid, this.filters);
};

/**
 * Shows the previous result page
 */
ResultList.prototype.showPrevious = function()
{
    this.getActivePane().showPrevious(this.ssid, this.filters);
};

/**
 * Shows the next result page
 */
ResultList.prototype.showNext = function()
{
    this.getActivePane().showNext(this.ssid, this.filters);
};

/**
 * Shows the first page of results
 */
ResultList.prototype.showFirst = function()
{
    this.getActivePane().showFirst(this.ssid, this.filters);
};

/**
 * Shows the last page of results
 */
ResultList.prototype.showLast = function()
{
    this.getActivePane().showLast(this.ssid, this.filters);
};

/**
 * Updates the result counts when the search status is updated.
 */
ResultList.prototype.updateResultCounts = function()
{
    // Update the count for each tab with the number of results that have been found.
    for (var i = 0; i < this.tabCount; ++i)
    {
        // Update the counts on the tab label
        var resultCountEle = document.getElementById("results_count_" + i);
        if (resultCountEle !== null)
        {
            var tabDisplayedCount = resultCountEle.innerHTML;
            if (this.resultPanes[i].displayCount === 0 || tabDisplayedCount == "0" || tabDisplayedCount === "")
            {
                // Update the result count element with the number of results
                this.updateResultCounter(i);
            }
        }
    }

    this.calculateDisplayTotal();

    var unseenResultCount = this.getTotalFilteredResults() - this.displayTotal;
    DWRUtil.setValue("unseenResultCount", unseenResultCount);

    var el = document.getElementById("more-results-info");

    // If there are unseen results and either we already have displayed some results
    // or the search has finished then show the link.
    if (unseenResultCount > 0 && (this.displayTotal > 0 || this.isSearchFinished()))
    {
        el.style.visibility = "visible";
    }
    else
    {
        el.style.visibility = "hidden";
    }

    this.updateTopResults();
};

/**
 * Updates the ui widgets that show the progress of the search
 */
ResultList.prototype.updateSearchProgress = function()
{
    var bar = document.getElementById("loading-bar");

    // If there are no collections, which is usually the case for refine search,
    // hide the loading bar
    if (this.resultListStatus.totalNumberCollections === 0)
    {
        bar.style.visibility = "hidden";
        return;
    }

    DWRUtil.setValue("totalCollections", DWRUtil.toDescriptiveString(this.resultListStatus.totalNumberCollections));
    DWRUtil.setValue("totalCompleted", DWRUtil.toDescriptiveString(this.resultListStatus.completedCollections));

    var percentComplete = (this.resultListStatus.completedCollections == this.resultListStatus.totalNumberCollections) ?
                          1.0 : this.resultListStatus.completedCollections / this.resultListStatus.totalNumberCollections;

    var image = Math.round(percentComplete * 10);

    switch (image)
    {
        case 0 :
            bar.className="zero-percent";
            break;
        case 1:
            bar.className="ten-percent";
            break;
        case 2:
            bar.className="twenty-percent";
            break;
        case 3:
            bar.className="thirty-percent";
            break;
        case 4:
            bar.className="forty-percent";
            break;
        case 5:
            bar.className="fifty-percent";
            break;
        case 6:
            bar.className="sixty-percent";
            break;
        case 7:
            bar.className="seventy-percent";
            break;
        case 8:
            bar.className="eighty-percent";
            break;
        case 9:
            bar.className="ninety-percent";
            break;
        case 10:
            bar.className="one-hundred-percent";
            break;
    }

    bar.style.visibility = "";
};

/**
 * Shows and hides the filter panes (top and bottom)
 * @param visibility "hidden" or "visible"
 */
ResultList.prototype.setFilterPaneVisibility = function(visibility)
{
    if(document.getElementById('filter_results_form') !== null)
    {
        document.getElementById('filter_results_form').style.visibility = visibility;
    }

    if(document.getElementById('filter_results_form_bottom') !== null)
    {
        document.getElementById('filter_results_form_bottom').style.visibility = visibility;
    }
};

/**
 * This method updates the Yahoo History manager state
 */
ResultList.prototype.updateHistory = function()
{
    var selCollection = (this.getActivePane().selectedCollection === "") ? "_" : this.getActivePane().selectedCollection;
    var selectedClusterLocation = this.clusterPanes[this.currentTabIndex].getSelectedClusterLocation();
    var clusterLocation = (selectedClusterLocation === "") ? "_" : selectedClusterLocation;
    var hist = this.currentTabIndex                               +
               "|" + this.getActivePane().startPosition           +
               "|" + selCollection                                +
               "|" + this.getActivePane().resultSortField +
               "|" + clusterLocation;

    if (hist != YAHOO.util.History.getCurrentState(ResultList.moduleName))
    {
        YAHOO.util.History.navigate(ResultList.moduleName, hist);
    }
};

/**
 * Gets the initial state from the yahoo history
 */
ResultList.prototype.getInitialState = function()
{
    var initialState = YAHOO.util.History.getBookmarkedState(ResultList.moduleName);

    if (!initialState)
    {
        initialState = this.currentTabIndex +
                       "|" + "0"            +
                       "|" + "_"            +
                       "|" + "rank"         +
                       "|" + "_";
    }

    // Set the inital history state
    YAHOO.util.History.register(ResultList.moduleName, initialState, this.onHistoryChange);
};

/**
 * Creates a new result state object give the state stored in the yahoo history mananger.
 * @param state
 */
function ResultListState(state)
{
    var stateArray = state.split("|");

    this.currentTabIndex    = parseInt(stateArray[0],10);
    this.startPosition      = parseInt(stateArray[1],10);
    this.selectedCollection = stateArray[2] == "_" ? "" : stateArray[2];
    this.resultSortField = stateArray[3];
    this.clusterLocation = stateArray[4] == "_" ? "" : stateArray[4];
}

/**
 * Handles the case where the history object has chaged its state.
 * @param state the current state of the history object.
 */
ResultList.prototype.onHistoryChange = function(state)
{
    // Get the state object.
    var resultListState = new ResultListState(state);

    // Shorthand for the current instance
    var inst = ResultList.instance;

    // Get the currently selectectd cluster id and the cluster id from the history
    var selectedClusterId = inst.clusterPanes[inst.currentTabIndex].getSelectedClusterId();
    var historyClusterId  = inst.clusterPanes[inst.currentTabIndex].clusterIdFromClusterLocation(resultListState.clusterLocation);

    // Get the active pane
    var activePane = inst.getActivePane();

    if (resultListState.currentTabIndex != inst.currentTabIndex)
    {
        inst.switchTabs(resultListState.currentTabIndex, resultListState);
    }
    else if (!historyClusterId && selectedClusterId)
    {
        inst.clusterPanes[inst.currentTabIndex].selectNodeByClusterId("");        
        inst.onAllResultsClicked(inst.currentTabIndex + inst.tabCount);
    }
    else if (historyClusterId && historyClusterId != selectedClusterId)
    {
        inst.clusterInitialState = resultListState;
        inst.selectCluster();
    }
    else
    {
        // if any of the other states have changed, then we will need to reload.
        if (resultListState.startPosition      != activePane.startPosition           ||
            resultListState.selectedCollection != activePane.selectedCollection      ||
            resultListState.resultSortField    != activePane.resultSortField)
        {
            activePane.startPosition      = resultListState.startPosition;
            activePane.selectedCollection = resultListState.selectedCollection;
            activePane.resultSortField    = resultListState.resultSortField;

            activePane.getPageOfResults(activePane.startPosition, false, inst.ssid, inst.filters);
        }
    }
};

/**
 * Gets the current state of the yahoo history
 */
ResultList.prototype.getCurrentState = function()
{
    var state = YAHOO.util.History.getCurrentState(ResultList.moduleName);

    return new ResultListState(state);
};

/**
 * Handler for the user action of clicking on one of the displayed tabs in the UI
 * @param which_tab the tab to switch to
 * @parma initialState the initial state of the result pane
 */
ResultList.prototype.switchTabs = function(which_tab, initialState)
{
    // Hide the correct cluster list for the current pane
    if (this.clusterPanes[this.currentTabIndex])
    {
        this.clusterPanes[this.currentTabIndex].hideClusters();
    }

    // Get and temporarily hide the filter panes while we calculate things.
    this.setFilterPaneVisibility("hidden");

    // Set the selected tab
    var selectedTab = document.getElementById("tab_" + which_tab);
    if (selectedTab !== null)
    {
        this.setSelectedTab(selectedTab);
    }

    // Set the selected container
    this.setSelectedContainer(document.getElementById("tab_content_" + this.activeTabPanes[which_tab].paneId));

    this.currentTabIndex = which_tab;

    // Update the description for the current tab
    if (document.getElementById("tab-description") !== null)
    {
        document.getElementById("tab-description").innerHTML = this.getActivePane().description;
    }

    // Get the active pane
    var activePane = this.getActivePane();

    // if the initialState is being set
    if (initialState)
    {
        activePane.startPosition      = initialState.startPosition;
        activePane.selectedCollection = initialState.selectedCollection;
        activePane.resultSortField    = initialState.resultSortField;
    }

    if (initialState && initialState.clusterLocation)
    {
        this.clusterInitialState = initialState;
    }
    else
    {
        // Update the two drop down boxes and pagination
        activePane.setSortByOptions();
        activePane.setLimitToOptions();
        activePane.paginate();

        // If there are no results to display
        if (activePane.resultCount === 0)
        {
            // if there are no results displayed in the pane and there are results to retrieve, get them
            if (activePane.displayCount === 0 && this.resultListStatus !== null && this.resultListStatus.paneCounts[this.currentTabIndex])
            {
                // Set the selected container to the retrieving results... container
                this.setSelectedContainer(document.getElementById("retrieving-results-tab-message"));

                this.showPage(0, true);
            }
            else if (this.isSearchFinished())
            {
                this.setSelectedContainer(document.getElementById("no-results-message"));
            }
            else
            {
                this.setSelectedContainer(document.getElementById("searching-tab-message"));
            }
        }
        else
        {
            // Show the filter panes
            this.setFilterPaneVisibility("visible");
        }
    }

    // Display the cluster list for the selected tab
    if (this.clusterPanes[this.currentTabIndex])
    {
        this.clusterPanes[this.currentTabIndex].showClusters();
    }

    this.updateHistory();
};

/**
 * Sets the currently selected tab element and resets the previously selected
 * tab element
 * @param newSelectedTab the newly selected tab
 */
ResultList.prototype.setSelectedTab = function(newSelectedTab)
{
    if (this.selectedTab !== null)
    {
        this.selectedTab.className = "";
    }

    newSelectedTab.className = "Selected";
    if (newSelectedTab.blur) { newSelectedTab.blur(); }

    this.selectedTab = newSelectedTab;
};

/**
 * Sets the currently selected container element and hides the previously selected
 * container element
 * @param newSelectedContainer the newly selected container
 */
ResultList.prototype.setSelectedContainer = function(newSelectedContainer)
{
    if (this.selectedContainer !== null)
    {
        this.selectedContainer.className = "Removed";
    }

    newSelectedContainer.className = "";

    this.selectedContainer = newSelectedContainer;
};

/**
 * Handles condidtions associated with a search status of "finished".
 */
ResultList.prototype.handleSearchFinished = function()
{
    var unseenResultCount = this.getTotalFilteredResults() - this.displayTotal;
    DWRUtil.setValue("unseenResultCount", unseenResultCount);

    // Hide all of the auxiliary panes by setting their class to "Removed"
    var elementIds = ["searching-tab-message", "no-results-message", "empty-tab-message", "retrieving-results-tab-message"];
    for (var i = 0; i < elementIds.length; ++i)
    {
        var elem = document.getElementById(elementIds[i]);
        elem.className = "Removed";
    }

    // Show the search completed pop-up.
    if (unseenResultCount > 0 && this.refreshMode == "PROMPT" && this.displayMoreResultsDialog)
    {
        this.showSearchPopup(unseenResultCount);
    }

    // Handle cases associated with no unseen results.
    if (unseenResultCount <= 0)
    {
        if (this.displayTotal === 0)
        {
            this.setSelectedContainer(document.getElementById("no-results-message"));
        }
        else if (this.getActivePane().displayCount === 0)
        {
            this.setSelectedContainer(document.getElementById("empty-tab-message"));
        }
    }
    // Handle cases where at least one pane has some results displayed.
    else if (this.getActivePane().displayCount === 0)
    {
        this.setSelectedContainer(document.getElementById("empty-tab-message"));
    }
 };

/**
 * Creates the search complete popup
 */
ResultList.prototype.createSearchPopup = function()
{
    document.getElementById("search-popup-window").style.display = "";

    this.searchPopup =  new YAHOO.widget.Dialog(
        "search-popup-window",
        {
            width      : "330px",
            fixedcenter: true,
            visible    : false,
            modal      : true,
            //close:false,
            underlay:"shadow",
            draggable:true,
            constraintoviewport : true,
            buttons : [ { text:ResultList.searchPopupButton1Text, handler:function(){ResultList.instance.handleSearchPopup(true);}, isDefault:true },
                        { text:ResultList.searchPopupButton2Text, handler:function(){ResultList.instance.handleSearchPopup(false);} } ]
        }
    );

    this.searchPopup.render();
};


/**
 * Update and display the search popup dialog.
 * We create a "canvas" iframe just beneath so that IE 5.5 and 6 will display
 * the div correctly over select elements.
 */
ResultList.prototype.showSearchPopup = function(resultCount)
{
    var count = document.getElementById("search_popup_resultCount");
    count.innerHTML = resultCount;

    this.searchPopup.show();
    this.searchPopup.center();
};

/**
 * Method called by the results pop-up to finish the search with a final refresh
 * or not, and to set the refresh mode if needed.
 * @param refresh true if the page should be refreshed
 */
ResultList.prototype.handleSearchPopup = function(refresh)
{
    this.searchPopup.hide();
    var disablePopup = document.getElementById("show_popup").checked;
    ResultListConnector.onSearchFinishConfirmed(disablePopup);
    if (refresh)
    {
        this.addResults();
    }
};

/**
 * Callback method for ResultListConnector.getResults* methods.  The return value contains
 * a resultContainer, which contains the results requested.  It then calls into the
 * appropriate resultPane's update method to display the data.
 * @param resultContainer the object that contains the new values to dsiplay in the
 * resultPane.
 */
ResultList.getResults_callback = function(resultContainer)
{
    ResultList.instance.setResults(resultContainer);
};

/**
 * The error handler method for calls to ResultListConnector.getResults
 * and ResultListConnector.getResultsForIds
 * @param message the error message to be displayed
 */
ResultList.getResults_errorHandler = function(message, info)
{
    ClusterPane.blockCalls = false;
    DWRHelper.displayDWRError("ResultList.getResults_callback", message, info);
};

ResultList.setClippingsCount_errorHandler = function(message, info)
{
    DWRHelper.displayDWRError("ResultList.setClippingsCount", message, info);
};

/**
 * Processes the result container that is received from calls to getResults...
 * @param resultContainer the object that contains the new values to dsiplay in the
 * resultPane.
 */
ResultList.prototype.setResults = function(resultContainer)
{
    ClusterPane.blockCalls = false;
    
    var paneIndex = resultContainer.paneIndex;

    // Get the result panel where the results will be stored
    var tabContentElement = document.getElementById("tab_content_" + paneIndex);

    // Get the result pane object for this index
    var resultPane = this.resultPanes[paneIndex];

    // Calculate the maximum total counts.  This is the maximum of resultContainer.totalResults and the
    // paneCounts from the resultList status
    var statusIndex = (paneIndex < this.tabCount) ? paneIndex : paneIndex - this.tabCount;
    var maxTotalCounts = Math.max(resultContainer.totalResults, this.resultListStatus.paneCounts[statusIndex]);

    // if there are currently no results displayed for this pane, generate the clusters
    // for the pane.
    if (resultPane.displayCount === 0 && maxTotalCounts > 0 && paneIndex < this.tabCount)
    {
        if (this.clusterPanes[paneIndex])
        {
            this.clusterPanes[paneIndex].getClusters(this.ssid, this.isInActiveTab(paneIndex),
                                                     maxTotalCounts, this.isSearchFinished(),
                                                     this.filters);
        }

        this.updateResultCounter(paneIndex, maxTotalCounts);

        // Show the filter panes
        this.setFilterPaneVisibility("visible");        
    }

    resultPane.setCollectionCounts(resultContainer.collectionCounts);

    resultPane.resultCount      = resultContainer.resultCount;
    resultPane.startPosition    = resultContainer.startPosition;
    resultPane.totalResultCount = resultContainer.totalResults;
    resultPane.displayCount     = maxTotalCounts;
    
    resultPane.update(resultContainer, tabContentElement);

    // if this pane is in the currently selected tab and it is not displayed, then show it
    if (this.isInActiveTab(paneIndex))
    {
        this.setSelectedContainer(tabContentElement);
        this.activeTabPanes[this.currentTabIndex] = resultPane;

        if (resultContainer.totalResults === 0)
        {
            this.setSelectedContainer(document.getElementById("empty-tab-message"));
        }
    }

    this.calculateDisplayTotal();

    // if this is a return from a cluster, select the node in the cluster
    if (resultContainer.clusterId !== null)
    {
        var clusterIndex = paneIndex - this.tabCount;
        this.clusterPanes[clusterIndex].selectNodeByClusterId(resultContainer.clusterId);
    }

    this.updateHistory();

    if (this.clusterInitialState)
    {
        // if any of the other states have changed, then we will need to reload.
        if (this.clusterInitialState.startPosition      != this.getActivePane().startPosition      ||
            this.clusterInitialState.selectedCollection != this.getActivePane().selectedCollection ||
            this.clusterInitialState.resultSortField    != this.getActivePane().resultSortField      )
        {
            this.getActivePane().startPosition   = this.clusterInitialState.startPosition;
            this.getActivePane().resultSortField = this.clusterInitialState.resultSortField;
            this.getActivePane().setSelectedCollection(this.clusterInitialState.selectedCollection);
            this.getActivePane().getPageOfResults(this.getActivePane().startPosition, false, this.ssid, this.filters);
        }

        this.clusterInitialState = null;
    }
};

/**
 * Updates the result count element for the given tab with the value from the
 * paneCounts array in the resultListStatus
 * @param tabIndex the index of the tab
 */
ResultList.prototype.updateResultCounter = function(index, count)
{
    var resultCountElement = document.getElementById("results_count_" + index);
    if (resultCountElement !== null)
    {
        if (typeof count == "undefined")
        {
            count = this.resultListStatus.paneCounts[index];
        }
        resultCountElement.innerHTML = count;
    }
};

/**
 * Updates the controls that are used to keep track of result counts
 */
ResultList.prototype.updateTopResults = function()
{
    if (document.getElementById("topResultCount") != null)
    {
        document.getElementById("topResultCount").innerHTML = formatInteger(this.resultListStatus.totalNumberResults);
    }

    if (document.getElementById("possibleResultCount") != null)
    {
        document.getElementById("possibleResultCount").innerHTML = formatInteger(this.resultListStatus.totalPossibleResults);
    }
}

/**
 * This method calculates the total number of results that can be displayed by summing
 * the results from each of the resultPanes.  If a resultPane does not have any results
 * displayed, it adds the totalResultCount.  If it does, it means that ResultList is no
 * longer updating its count, so use the displayCount for that pane.
 */
ResultList.prototype.calculateDisplayTotal = function()
{
    this.displayTotal = 0;
    for (var i = 0; i < this.tabCount; ++i)
    {
        if (this.resultPanes[i].displayCount === 0)
        {
            this.displayTotal += this.resultListStatus.paneCounts[i];
        }
        else
        {
            this.displayTotal += this.resultPanes[i].displayCount;
        }
    }
};

/**
 * Detects if the current pane is in the currently selected tab.
 * @param paneIndex the index of the pane to be checked
 * @return true if the pane is in the currently dispalyed tab
 */
ResultList.prototype.isInActiveTab = function(paneIndex)
{
    return (paneIndex == this.currentTabIndex ||
            paneIndex - this.tabCount == this.currentTabIndex);
};

/**
 * This method is called in response to the onlableclick event in the cluster tree.
 * @param cluster the cluster object associated with the clicked cluster label.
 * @param displayPaneIndex the index to the result pane in which the clusters results
 * are to be displayed.
 * @param clusterGroup the name of the group that this cluster is associated with
 */
ResultList.prototype.onClusterClicked = function(cluster, displayPaneIndex, clusterGroup)
{
    this.retrieveClusterResults(cluster.clusterId, displayPaneIndex, clusterGroup, 0);
};

/**
 * Selects a cluster based on the clusterInitialState
 */
ResultList.prototype.selectCluster = function()
{
    var selectedClusterId = this.clusterPanes[this.clusterInitialState.currentTabIndex].clusterIdFromClusterLocation(this.clusterInitialState.clusterLocation);

    if(typeof(selectedClusterId) == "undefined")
    {
        this.onAllResultsClicked(this.clusterInitialState.currentTabIndex + this.tabCount);
    }
    else
    {

        // Get the results for the selected cluster.
        this.retrieveClusterResults(selectedClusterId, this.clusterInitialState.currentTabIndex + this.tabCount,
                this.clusterInitialState.currentTabIndex, this.clusterInitialState.startPosition);
    }
};

/**
 * Event fired from the cluster pane following the creation of the cluster tree object.
 * If an initial cluster state is being restored, then the results for the clusters are
 * retrieved here.
 */
ResultList.prototype.onCreateClusterTree = function()
{
    if (this.clusterInitialState)
    {
        this.selectCluster();
    }
};

/**
 * This method is called to retrieve results for a given cluster
 * @param clusterId the id of the cluster to get results for
 * @param displayPaneIndex the index to the result pane in which the clusters results
 * are to be displayed.
 * @param clusterGroup the name of the group that this cluster is associated with
 * @param startPosition the position within the results to retrieve from
 */
ResultList.prototype.retrieveClusterResults = function(clusterId, displayPaneIndex, clusterGroup, startPosition)
{
    // Reset the collectionCounts
    this.resultPanes[displayPaneIndex].setCollectionCounts(null);

    // Reset the selected collection
    this.resultPanes[displayPaneIndex].resetSelectedCollection();

    ResultListConnector.getResultsForCluster(this.ssid, displayPaneIndex, clusterGroup, clusterId,
            startPosition, Paginator.resultsPerPage, this.filters, this.resultPanes[displayPaneIndex].resultSortField,
            ResultList.getResultsDWRObject);
};

/**
 * This method is called in response to the onlableclick event in the cluster tree
 * when the user clicks on the "All Results" node in the tree.
 * @param displayPaneIndex the index to the result pane in which the clusters results
 * are normally displayed.
 */
ResultList.prototype.onAllResultsClicked = function(displayPaneIndex)
{
    var paneIndex = displayPaneIndex - this.tabCount;

    var newResultPane = this.resultPanes[paneIndex];
    this.activeTabPanes[this.currentTabIndex] = newResultPane;

    if (newResultPane.displayCount === 0)
    {
        this.showPage(-1, true);
    }
    else
    {
        this.setSelectedContainer(document.getElementById("tab_content_" + paneIndex));

        // Update the two drop down boxes
        newResultPane.setSortByOptions();
        newResultPane.setLimitToOptions();

        newResultPane.paginate();

        this.updateHistory();
    }
};

/**
 * The object used when making calls to getResults
 */
ResultList.getResultsDWRObject = {
  callback:     ResultList.getResults_callback,
  timeout:      30000,
  errorHandler: ResultList.getResults_errorHandler
};

/**
 * Makes an AJAX call to ResultlistConnector.getSpellingSuggestion and passes it
 * the full record setarch string.
 */
ResultList.prototype.getSpellingSuggestion = function()
{
    var expression = "";

    for(var i = 0; i < this.spellSuggestFieldsList.length; i++)
    {
        //Change this value so we can grab the right value from the URL
        if(ResultList.instance.spellSuggestFieldsList[i] == ResultList.spellFieldSummary)
        {
            ResultList.instance.spellSuggestFieldsList[i] = ResultList.spellFieldSnippet;
        }

        var regexpString = "%26"+this.spellSuggestFieldsList[i]+"%3D(.*?)%26";
        var regexp = new RegExp(regexpString);
        var myMatch = window.location.href.match(regexp);
        var field = null;

        if (myMatch)
        {
            // We take the SECOND element in the array because it contains what was
            // matched bewtween the parens in the regexp
            field = myMatch[1];

            // Decode the full record match...  Then replace the + with spaces
            field = decodeURIComponent(field);
            field = field.replace(/\+/g, " ");

            if(expression == "")
            {
                expression = field;
            }
            else
            {
                expression = expression + "!#!" + field;
            }
        }
        else
        {
            if(expression == "")
            {
                expression = "NO_FIELD_ENTRY";
            }
            else
            {
                expression = expression + "!#!" + "NO_FIELD_ENTRY";
            }
        }
    }

    ResultListConnector.getSpellingSuggestion(expression, ResultList.getSpellingSuggestionDWRObject);
};

/**
 * Callback function to the method ResultListConnector.getSpellingSuggestion
 * Displays the spelling suggestion on the view if it is not empty
 * @param data the data received from the AJAX call.
 */
ResultList.getSpellingSuggestion_callback = function(suggestion)
{
    if (suggestion)
    {
        var linkString = "";
        var suggestionList = [];

        suggestionList = suggestion.split("!#!");

        //Match the suggestion to the field name
        for(var i = 0; i < ResultList.instance.spellSuggestFieldsList.length; i++)
        {
            if(!(suggestionList[i] == "NO_FIELD_ENTRY"))
            {
                //Change this so it matches the UI
                if(ResultList.instance.spellSuggestFieldsList[i] == ResultList.spellFieldSnippet)
                {
                    ResultList.instance.spellSuggestFieldsList[i] = ResultList.spellFieldSummary;
                }

                linkString = linkString + ResultList.instance.spellSuggestFieldsList[i] + ": " + suggestionList[i] + " / ";
            }
        }

        //Remove the last slash
        linkString =  linkString.slice(0, -3);

        document.getElementById("spellBlock").style.display = "inline";
        document.getElementById("spellingSuggestion").innerHTML = decodeURIComponent(linkString);
    }
    else
    {
        var node = document.getElementById("spellBlock");
        var parent = node.parentNode;
        parent.removeChild(node);
    }
};

/**
 * This method is called when the user clicks on the link to rerun the search.
 * It puts together a URL from the spelling suggestion data.
 */
ResultList.prototype.rerunSearchWithSpellSuggestions = function()
{
    var i, nameValue, suggestString = "";

    var suggestions = document.getElementById('spellingSuggestion').innerHTML.split("/");

    for(var i = 0; i < suggestions.length; i++)
    {

        for (i = 0; i < suggestions.length; i++)
        {
            suggestions[i] = YAHOO.lang.trim(suggestions[i]);
            nameValue = suggestions[i].split(":");
            nameValue[0] = YAHOO.lang.trim(nameValue[0]);
            nameValue[1] = YAHOO.lang.trim(nameValue[1]);

            if (nameValue[0] == ResultList.spellFieldSummary)
            {
                nameValue[0] = ResultList.spellFieldSnippet;
            }

            suggestString += nameValue[0] + "=" + encodeURIComponent(nameValue[1]) + "&"
        }

        var url = "search.html?get=true&newSearch=true&ssid=" + encodeURIComponent(this.ssid) + "&" + suggestString;
        window.location.href = url;
    }
};


/**
 * Error handler from the call to getSpellingSuggestion
 * @param message the error message
 * @param info a stack trace, and futher info
 */
ResultList.getSpellingSuggestion_errorHandler = function(message, info)
{
    if (DWRHelper.debugMode)
    {
        ResultList.pageErrorHandler("ResultListConnector.getSpellingSuggestion", message, info);
    }
};

/**
 * The object used when making calls to getSpellingSuggestion
 */
ResultList.getSpellingSuggestionDWRObject = {
    callback:     ResultList.getSpellingSuggestion_callback,
    timeout:      DWRHelper.ajaxTimeout,
    errorHandler: ResultList.getSpellingSuggestion_errorHandler
};