/// <summary> Constructor for a new instance of the Metadata_Browse_AggregationViewer class </summary>
        /// <param name="Current_Mode"> Mode / navigation information for the current request</param>
        /// <param name="Current_Aggregation"> Current item aggregation object to display </param>
        /// <param name="Tracer">Trace object keeps a list of each method executed and important milestones in rendering</param>
        public Metadata_Browse_AggregationViewer(SobekCM_Navigation_Object Current_Mode, Item_Aggregation Current_Aggregation, Custom_Tracer Tracer)
            : base(Current_Aggregation, Current_Mode)
        {
            string defaultBrowseBy = Current_Aggregation.Default_BrowseBy;

            // If there is not info browse mode listed, use the default
            if (Current_Mode.Info_Browse_Mode.Length == 0)
                Current_Mode.Info_Browse_Mode = defaultBrowseBy;
            if ((Current_Mode.Info_Browse_Mode.Length == 0) && (Current_Aggregation.Has_Browse_By_Pages))
                Current_Mode.Info_Browse_Mode = Current_Aggregation.Browse_By_Pages(Current_Mode.Language)[0].Code;

            // Get this browse
            browseObject = Current_Aggregation.Get_Browse_Info_Object(Current_Mode.Info_Browse_Mode);

            // Was this a metadata browseby, or just a static html?
            if (( browseObject == null ) || ( browseObject.Source != Item_Aggregation_Browse_Info.Source_Type.Static_HTML))
            {
                // Determine the correct metadata code
                string metadata_code = Current_Mode.Info_Browse_Mode.Trim().Replace("_", " ");
                Current_Mode.Info_Browse_Mode = metadata_code;

                // Only get values if there was a metadata code
                if (metadata_code.Length > 0)
                {
                    // Check the cache for this value
                    List<string> cacheInstance = Cached_Data_Manager.Retrieve_Aggregation_Metadata_Browse(Current_Mode.Aggregation, Current_Mode.Info_Browse_Mode, Tracer);

                    if (cacheInstance != null)
                    {
                        results = cacheInstance;
                    }
                    else
                    {
                        results = SobekCM_Database.Get_Item_Aggregation_Metadata_Browse(Current_Mode.Aggregation, Current_Mode.Info_Browse_Mode, Tracer);
                        Cached_Data_Manager.Store_Aggregation_Metadata_Browse(Current_Mode.Aggregation, Current_Mode.Info_Browse_Mode, results, Tracer);
                    }
                }
            }
        }
        /// <summary> Adds the ALL ITEMS and NEW ITEMS browses to the item aggregation, if the display options and last added
        /// item date call for it </summary>
        /// <param name="ThisObject"> Item aggregation to which to add the ALL ITEMS and NEW ITEMS browse</param>
        /// <remarks>This method is always called while building an item aggregation, irregardless of whether there is an
        /// item aggregation configuration XML file or not.</remarks>
        protected static void Add_All_New_Browses(Item_Aggregation ThisObject)
        {
            // If this is the main home page for this site, do not show ALL since we cannot browse ALL items
            if (!ThisObject.Can_Browse_Items )
                return;

            // If this is in the display options, and the item browses
            if ((ThisObject.Display_Options.Length == 0) || (ThisObject.Display_Options.IndexOf("I") >= 0))
            {
                // Add the ALL browse, if there should be one
                ThisObject.Add_Child_Page(Item_Aggregation_Child_Page.Visibility_Type.MAIN_MENU, "all", String.Empty, "All Items");

                // Add the NEW search, if the ALL search exists
                if ((ThisObject.Get_Browse_Info_Object("all") != null) && (ThisObject.Show_New_Item_Browse))
                {
                    ThisObject.Add_Child_Page(Item_Aggregation_Child_Page.Visibility_Type.MAIN_MENU, "new", String.Empty, "Recently Added Items");
                }
            }
            else
            {
                // Add the ALL browse as an info
                ThisObject.Add_Child_Page(Item_Aggregation_Child_Page.Visibility_Type.NONE, "all", String.Empty, "All Items");
            }
        }
        /// <summary> Gets the browse or info object and any other needed data for display ( resultset or text to display) </summary>
        /// <param name="Current_Mode"> Mode / navigation information for the current request</param>
        /// <param name="Aggregation_Object"> Item Aggregation object</param>
        /// <param name="Base_Directory"> Base directory location under which the the CMS/info source file will be found</param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering </param>
        /// <param name="Browse_Object"> [OUT] Stores all the information about this browse or info </param>
        /// <param name="Complete_Result_Set_Info"> [OUT] Information about the entire set of results </param>
        /// <param name="Paged_Results"> [OUT] List of search results for the requested page of results </param>
        /// <param name="Browse_Info_Display_Text"> [OUT] Static HTML-based content to be displayed if this is browing a staticly created html source file </param>
        /// <returns> TRUE if successful, otherwise FALSE </returns>
        /// <remarks> This attempts to pull the objects from the cache.  If unsuccessful, it builds the objects from the
        /// database and hands off to the <see cref="Cached_Data_Manager" /> to store in the cache </remarks>
        public bool Get_Browse_Info(SobekCM_Navigation_Object Current_Mode,
                                    Item_Aggregation Aggregation_Object,
                                    string Base_Directory,
                                    Custom_Tracer Tracer,
                                    out Item_Aggregation_Browse_Info Browse_Object,
                                    out Search_Results_Statistics Complete_Result_Set_Info,
                                    out List<iSearch_Title_Result> Paged_Results,
                                    out HTML_Based_Content Browse_Info_Display_Text )
        {
            if (Tracer != null)
            {
                Tracer.Add_Trace("SobekCM_Assistant.Get_Browse_Info", String.Empty);
            }

            // Set output initially to null
            Browse_Object = null;
            Paged_Results = null;
            Complete_Result_Set_Info = null;
            Browse_Info_Display_Text = null;

            // First, make sure the browse submode is valid
            if ((Aggregation_Object.Aggregation_ID == -1) && (Current_Mode.Mode == Display_Mode_Enum.Simple_HTML_CMS))
            {
                string source = Base_Directory + "design\\info";
                string[] matching_file = Directory.GetFiles(source, Current_Mode.Info_Browse_Mode + ".*");
                if (matching_file.Length > 0)
                {
                    Browse_Object = new Item_Aggregation_Browse_Info(Item_Aggregation_Browse_Info.Browse_Info_Type.Info, Item_Aggregation_Browse_Info.Source_Type.Static_HTML, Current_Mode.Info_Browse_Mode, matching_file[0], Current_Mode.Info_Browse_Mode);
                }
            }
            else
            {
                Browse_Object = Aggregation_Object.Get_Browse_Info_Object(Current_Mode.Info_Browse_Mode);
            }
            if (Browse_Object == null)
            {
                Current_Mode.Error_Message = "Unable to retrieve browse/info item '" + Current_Mode.Info_Browse_Mode + "'";
                return false;
            }

            // Is this a table result, or a string?
            switch (Browse_Object.Data_Type)
            {
                case Item_Aggregation_Browse_Info.Result_Data_Type.Table:

                    // Set the current sort to ZERO, if currently set to ONE and this is an ALL BROWSE.
                    // Those two sorts are the same in this case
                    int sort = Current_Mode.Sort;
                    if ((Current_Mode.Sort == 0) && (Browse_Object.Code == "all"))
                        sort = 1;

                    // Special code if this is a JSON browse
                    string browse_code = Current_Mode.Info_Browse_Mode;
                    if (Current_Mode.Writer_Type == Writer_Type_Enum.JSON)
                    {
                        browse_code = browse_code + "_JSON";
                        sort = 12;
                    }

                    // Determine if this is a special search type which returns more rows and is not cached.
                    // This is used to return the results as XML and DATASET
                    bool special_search_type = false;
                    int results_per_page = 20;
                    if ((Current_Mode.Writer_Type == Writer_Type_Enum.XML) || (Current_Mode.Writer_Type == Writer_Type_Enum.DataSet))
                    {
                        results_per_page = 1000;
                        special_search_type = true;
                        sort = 2; // Sort by BibID always for these
                    }

                    // Set the flags for how much data is needed.  (i.e., do we need to pull ANYTHING?  or
                    // perhaps just the next page of results ( as opposed to pulling facets again).
                    bool need_browse_statistics = true;
                    bool need_paged_results = true;
                    if (!special_search_type)
                    {
                        // Look to see if the browse statistics are available on any cache for this browse
                        Complete_Result_Set_Info = Cached_Data_Manager.Retrieve_Browse_Result_Statistics(Aggregation_Object.Code, browse_code, Tracer);
                        if (Complete_Result_Set_Info != null)
                            need_browse_statistics = false;

                        // Look to see if the paged results are available on any cache..
                        Paged_Results = Cached_Data_Manager.Retrieve_Browse_Results(Aggregation_Object.Code, browse_code, Current_Mode.Page, sort, Tracer);
                        if (Paged_Results != null)
                            need_paged_results = false;
                    }

                    // Was a copy found in the cache?
                    if ((!need_browse_statistics) && ( !need_paged_results ))
                    {
                        if (Tracer != null)
                        {
                            Tracer.Add_Trace("SobekCM_Assistant.Get_Browse_Info", "Browse statistics and paged results retrieved from cache");
                        }
                    }
                    else
                    {
                        if (Tracer != null)
                        {
                            Tracer.Add_Trace("SobekCM_Assistant.Get_Browse_Info", "Building results information");
                        }

                        // Try to pull more than one page, so we can cache the next page or so
                        List<List<iSearch_Title_Result>> pagesOfResults;

                        // Get from the hierarchy object
                        if (Current_Mode.Writer_Type == Writer_Type_Enum.JSON)
                        {
                            Multiple_Paged_Results_Args returnArgs = SobekCM_Database.Get_Item_Aggregation_Browse_Paged(Current_Mode.Aggregation, "1900-01-01", false, 20, Current_Mode.Page, 0, need_browse_statistics, Aggregation_Object.Facets, need_browse_statistics, Tracer);
                            if (need_browse_statistics)
                            {
                                Complete_Result_Set_Info = returnArgs.Statistics;
                            }
                            pagesOfResults = returnArgs.Paged_Results;
                            if ((pagesOfResults != null) && (pagesOfResults.Count > 0))
                                Paged_Results = pagesOfResults[0];
                        }
                        else
                        {
                            Multiple_Paged_Results_Args returnArgs = Aggregation_Object.Get_Browse_Results(Browse_Object, Current_Mode.Page, sort, results_per_page, !special_search_type, need_browse_statistics, Tracer);
                            if (need_browse_statistics)
                            {
                                Complete_Result_Set_Info = returnArgs.Statistics;
                            }
                            pagesOfResults = returnArgs.Paged_Results;
                            if ((pagesOfResults != null) && (pagesOfResults.Count > 0))
                                Paged_Results = pagesOfResults[0];
                        }

                        // Save the overall result set statistics to the cache if something was pulled
                        if (!special_search_type)
                        {
                            if ((need_browse_statistics) && (Complete_Result_Set_Info != null))
                            {
                                Cached_Data_Manager.Store_Browse_Result_Statistics(Aggregation_Object.Code, browse_code, Complete_Result_Set_Info, Tracer);
                            }

                            // Save the overall result set statistics to the cache if something was pulled
                            if ((need_paged_results) && (Paged_Results != null))
                            {
                                Cached_Data_Manager.Store_Browse_Results(Aggregation_Object.Code, browse_code, Current_Mode.Page, sort, pagesOfResults, Tracer);
                            }
                        }
                    }
                    break;

                case Item_Aggregation_Browse_Info.Result_Data_Type.Text:
                    Browse_Info_Display_Text = Browse_Object.Get_Static_Content(Current_Mode.Language, Current_Mode.Base_URL, SobekCM_Library_Settings.Base_Design_Location + Aggregation_Object.objDirectory, Tracer);
                    break;
            }
            return true;
        }