Item viewer is substituted for the regular image/download viewers if an item is restricted by IP address range and is not accessible to the the current user
This class extends the abstract class abstractItemViewer and implements the iItemViewer interface.
Inheritance: SobekCM.Library.ItemViewer.Viewers.abstractItemViewer
        /// <summary> Constructor for a new instance of the Item_HtmlSubwriter class </summary>
        /// <param name="ShowToc"> Flag indicates whether to show the table of contents open for this item </param>
        /// <param name="Show_Zoomable"> Flag indicates if the zoomable server is available </param>
        /// <param name="Item_Restricted_Message"> Message to be shown because this item is restriced from the current user by IP address </param>
        /// <param name="RequestSpecificValues"> All the necessary, non-global data specific to the current request </param>
        public Item_HtmlSubwriter(bool ShowToc, bool Show_Zoomable,
                                  string Item_Restricted_Message,
                                  RequestCache RequestSpecificValues)
            : base(RequestSpecificValues)
        {
            showToc = ShowToc;
            showZoomable = Show_Zoomable;
            itemCheckedOutByOtherUser = false;
            userCanEditItem = false;
            searchResultsCount = 0;

            // Determine if this item is an EAD
            isEadTypeItem = (RequestSpecificValues.Current_Item.Get_Metadata_Module(GlobalVar.EAD_METADATA_MODULE_KEY) != null);

            // Determine if this item is actually restricted
            itemRestrictedFromUserByIp = Item_Restricted_Message.Length > 0;

            // Determine if this user can edit this item
            if (RequestSpecificValues.Current_User != null)
            {
                userCanEditItem = RequestSpecificValues.Current_User.Can_Edit_This_Item(RequestSpecificValues.Current_Item.BibID, RequestSpecificValues.Current_Item.Bib_Info.SobekCM_Type_String, RequestSpecificValues.Current_Item.Bib_Info.Source.Code, RequestSpecificValues.Current_Item.Bib_Info.HoldingCode, RequestSpecificValues.Current_Item.Behaviors.Aggregation_Code_List);
            }

            // If this item is restricted by IP than alot of the upcoming code is unnecessary
            if (( RequestSpecificValues.Current_User != null ) && ((!itemRestrictedFromUserByIp) || ( userCanEditItem ) || ( RequestSpecificValues.Current_User.Is_Internal_User )))
            {
                #region Region suppressed currently - was for adding feature to a map image?

                //// Searching for EAD/EAC type items is different from others
                //if (!isEadTypeItem)
                //{
                //    // If there is a coordinate search, and polygons, do that
                //    // GEt the geospatial metadata module
                //    GeoSpatial_Information geoInfo = RequestSpecificValues.Current_Item.Get_Metadata_Module(GlobalVar.GEOSPATIAL_METADATA_MODULE_KEY) as GeoSpatial_Information;
                //    if ((geoInfo != null) && (geoInfo.hasData))
                //    {
                //        if ((currentMode.Coordinates.Length > 0) && (geoInfo.Polygon_Count > 1))
                //        {
                //            // Determine the coordinates in this search
                //            string[] splitter = currentMode.Coordinates.Split(",".ToCharArray());

                //            if (((splitter.Length > 1) && (splitter.Length < 4)) || ((splitter.Length == 4) && (splitter[2].Length == 0) && (splitter[3].Length == 0)))
                //            {
                //                Double.TryParse(splitter[0], out providedMaxLat);
                //                Double.TryParse(splitter[1], out providedMaxLong);
                //                providedMinLat = providedMaxLat;
                //                providedMinLong = providedMaxLong;
                //            }
                //            else if (splitter.Length >= 4)
                //            {
                //                Double.TryParse(splitter[0], out providedMaxLat);
                //                Double.TryParse(splitter[1], out providedMaxLong);
                //                Double.TryParse(splitter[2], out providedMinLat);
                //                Double.TryParse(splitter[3], out providedMinLong);
                //            }

                //            // Now, if there is length, determine the count of results
                //            searchResultsString = new List<string>();
                //            if (searchResultsString.Count > 0)
                //            {
                //                searchResultsCount = searchResultsString.Count;

                //                // Also, look to see where the current point lies in the matching, current polygon
                //                if ((providedMaxLong == providedMinLong) && (providedMaxLat == providedMinLat))
                //                {
                //                    foreach (Coordinate_Polygon itemPolygon in geoInfo.Polygons)
                //                    {
                //                        // Is this the current page?
                //                        if (itemPolygon.Page_Sequence == currentMode.Page)
                //                        {
                //                            if (itemPolygon.is_In_Bounding_Box(providedMaxLat, providedMaxLong))
                //                            {
                //                                searchMatchOnThisPage = true;
                //                                ReadOnlyCollection<Coordinate_Point> boundingBox = itemPolygon.Bounding_Box;
                //                                featureYRatioLocation = Math.Abs(((providedMaxLat - boundingBox[0].Latitude)/(boundingBox[0].Latitude - boundingBox[1].Latitude)));
                //                                featureXRatioLocation = Math.Abs(((providedMaxLong - boundingBox[0].Longitude)/(boundingBox[0].Longitude - boundingBox[1].Longitude)));
                //                            }
                //                        }
                //                    }
                //                }
                //            }
                //        }
                //    }
                //}

                #endregion

                // Is this a postback?
                if (RequestSpecificValues.Current_Mode.isPostBack)
                {
                    // Handle any actions from standard user action (i.e., email, add to bookshelf, etc. )
                    if (HttpContext.Current.Request.Form["item_action"] != null)
                    {
                        string action = HttpContext.Current.Request.Form["item_action"].ToLower().Trim();

                        if (action == "email")
                        {
                            string address = HttpContext.Current.Request.Form["email_address"].Replace(";", ",").Trim();
                            string comments = HttpContext.Current.Request.Form["email_comments"].Trim();
                            string format = HttpContext.Current.Request.Form["email_format"].Trim().ToUpper();
                            if (address.Length > 0)
                            {
                                // Determine the email format
                                bool is_html_format = format != "TEXT";

                                // CC: the user, unless they are already on the list
                                string cc_list = RequestSpecificValues.Current_User.Email;
                                if (address.ToUpper().IndexOf(RequestSpecificValues.Current_User.Email.ToUpper()) >= 0)
                                    cc_list = String.Empty;

                                // Send the email
                                HttpContext.Current.Session.Add("ON_LOAD_MESSAGE", !Item_Email_Helper.Send_Email(address, cc_list, comments, RequestSpecificValues.Current_User.Full_Name,RequestSpecificValues.Current_Mode.Instance_Abbreviation,RequestSpecificValues.Current_Item,is_html_format,HttpContext.Current.Items["Original_URL"].ToString(), RequestSpecificValues.Current_User.UserID)
                                    ? "Error encountered while sending email" : "Your email has been sent");

                                HttpContext.Current.Response.Redirect( HttpContext.Current.Items["Original_URL"].ToString(), false);
                                HttpContext.Current.ApplicationInstance.CompleteRequest();
                                RequestSpecificValues.Current_Mode.Request_Completed = true;
                                return;
                            }
                        }

                        if (action == "add_item")
                        {
                            string usernotes = HttpContext.Current.Request.Form["add_notes"].Trim();
                            string foldername = HttpContext.Current.Request.Form["add_bookshelf"].Trim();
                            bool open_bookshelf = HttpContext.Current.Request.Form["open_bookshelf"] != null;

                            if (SobekCM_Database.Add_Item_To_User_Folder(RequestSpecificValues.Current_User.UserID, foldername, RequestSpecificValues.Current_Item.BibID, RequestSpecificValues.Current_Item.VID, 0, usernotes, RequestSpecificValues.Tracer))
                            {
                                RequestSpecificValues.Current_User.Add_Bookshelf_Item(RequestSpecificValues.Current_Item.BibID, RequestSpecificValues.Current_Item.VID);

                                // Ensure this user folder is not sitting in the cache
                                CachedDataManager.Remove_User_Folder_Browse(RequestSpecificValues.Current_User.UserID, foldername, RequestSpecificValues.Tracer);

                                HttpContext.Current.Session.Add("ON_LOAD_MESSAGE", "Item was saved to your bookshelf.");

                                if (open_bookshelf)
                                {
                                    HttpContext.Current.Session.Add("ON_LOAD_WINDOW", "?m=lmfl" + foldername.Replace("\"", "%22").Replace("'", "%27").Replace("=", "%3D").Replace("&", "%26") + "&vp=1");
                                }
                            }
                            else
                            {
                                HttpContext.Current.Session.Add("ON_LOAD_MESSAGE", "ERROR encountered while trying to save to your bookshelf.");
                            }

                            HttpContext.Current.Response.Redirect(HttpContext.Current.Items["Original_URL"].ToString(), false);
                            HttpContext.Current.ApplicationInstance.CompleteRequest();
                            RequestSpecificValues.Current_Mode.Request_Completed = true;
                            return;
                        }

                        if (action == "remove")
                        {
                            if (SobekCM_Database.Delete_Item_From_User_Folders(RequestSpecificValues.Current_User.UserID, RequestSpecificValues.Current_Item.BibID, RequestSpecificValues.Current_Item.VID, RequestSpecificValues.Tracer))
                            {
                                RequestSpecificValues.Current_User.Remove_From_Bookshelves(RequestSpecificValues.Current_Item.BibID, RequestSpecificValues.Current_Item.VID);
                                CachedDataManager.Remove_All_User_Folder_Browses(RequestSpecificValues.Current_User.UserID, RequestSpecificValues.Tracer);
                                HttpContext.Current.Session.Add("ON_LOAD_MESSAGE", "Item was removed from your bookshelves.");
                            }
                            else
                            {
                                HttpContext.Current.Session.Add("ON_LOAD_MESSAGE", "ERROR encountered while trying to remove item from your bookshelves.");
                            }

                            HttpContext.Current.Response.Redirect(HttpContext.Current.Items["Original_URL"].ToString(), false);
                            HttpContext.Current.ApplicationInstance.CompleteRequest();
                            RequestSpecificValues.Current_Mode.Request_Completed = true;
                            return;
                        }

                        if (action.IndexOf("add_tag") == 0)
                        {
                            int tagid = -1;
                            if (action.Replace("add_tag", "").Length > 0)
                            {
                                tagid = Convert.ToInt32(action.Replace("add_tag_", ""));
                            }
                            string description = HttpContext.Current.Request.Form["add_tag"].Trim();
                            int new_tagid = SobekCM_Database.Add_Description_Tag(RequestSpecificValues.Current_User.UserID, tagid, RequestSpecificValues.Current_Item.Web.ItemID, description, RequestSpecificValues.Tracer);
                            if (new_tagid > 0)
                            {
                                RequestSpecificValues.Current_Item.Behaviors.Add_User_Tag(RequestSpecificValues.Current_User.UserID, RequestSpecificValues.Current_User.Full_Name, description, DateTime.Now, new_tagid);
                                RequestSpecificValues.Current_User.Has_Descriptive_Tags = true;
                            }

                            HttpContext.Current.Response.Redirect(HttpContext.Current.Items["Original_URL"].ToString(), false);
                            HttpContext.Current.ApplicationInstance.CompleteRequest();
                            RequestSpecificValues.Current_Mode.Request_Completed = true;
                            return;
                        }

                        if (action.IndexOf("delete_tag") == 0)
                        {
                            if (action.Replace("delete_tag", "").Length > 0)
                            {
                                int tagid = Convert.ToInt32(action.Replace("delete_tag_", ""));
                                if (RequestSpecificValues.Current_Item.Behaviors.Delete_User_Tag(tagid, RequestSpecificValues.Current_User.UserID))
                                {
                                    SobekCM_Database.Delete_Description_Tag(tagid, RequestSpecificValues.Tracer);
                                }
                            }
                            HttpContext.Current.Response.Redirect(HttpContext.Current.Items["Original_URL"].ToString(), false);
                            HttpContext.Current.ApplicationInstance.CompleteRequest();
                            RequestSpecificValues.Current_Mode.Request_Completed = true;
                            return;
                        }
                    }
                }

                // Handle any request from the internal header for the item
                if ((HttpContext.Current != null) && (HttpContext.Current.Request.Form["internal_header_action"] != null) && ( RequestSpecificValues.Current_User != null ))
                {
                    // Pull the action value
                    string internalHeaderAction = HttpContext.Current.Request.Form["internal_header_action"].Trim();

                    // Was this to save the item comments?
                    if (internalHeaderAction == "save_comments")
                    {
                        string new_comments = HttpContext.Current.Request.Form["intheader_internal_notes"].Trim();
                        if ( Resource_Object.Database.SobekCM_Database.Save_Item_Internal_Comments( RequestSpecificValues.Current_Item.Web.ItemID, new_comments))
                            RequestSpecificValues.Current_Item.Tracking.Internal_Comments = new_comments;
                    }

                    // Is this to change accessibility?
                    if ((internalHeaderAction == "public") || (internalHeaderAction == "private") || (internalHeaderAction == "restricted"))
                    {
                        int current_mask = RequestSpecificValues.Current_Item.Behaviors.IP_Restriction_Membership;
                        switch (internalHeaderAction)
                        {
                            case "public":
                                RequestSpecificValues.Current_Item.Behaviors.IP_Restriction_Membership = 0;
                                break;

                            case "private":
                                RequestSpecificValues.Current_Item.Behaviors.IP_Restriction_Membership = -1;
                                break;

                            case "restricted":
                                RequestSpecificValues.Current_Item.Behaviors.IP_Restriction_Membership = 1;
                                break;
                        }

                        // Is this new visibility different than the old one?
                        if (RequestSpecificValues.Current_Item.Behaviors.IP_Restriction_Membership != current_mask)
                        {
                            // Save this to the database
                            if (Resource_Object.Database.SobekCM_Database.Set_IP_Restriction_Mask(RequestSpecificValues.Current_Item.Web.ItemID, RequestSpecificValues.Current_Item.Behaviors.IP_Restriction_Membership, RequestSpecificValues.Current_User.UserName, String.Empty))
                            {
                                // Update the cached item
                                CachedDataManager.Remove_Digital_Resource_Object(RequestSpecificValues.Current_Item.BibID, RequestSpecificValues.Current_Item.VID, RequestSpecificValues.Tracer);
                                CachedDataManager.Store_Digital_Resource_Object(RequestSpecificValues.Current_Item.BibID, RequestSpecificValues.Current_Item.VID, RequestSpecificValues.Current_Item, RequestSpecificValues.Tracer);

                                // Update the web.config
                                Resource_Web_Config_Writer.Update_Web_Config(RequestSpecificValues.Current_Item.Source_Directory, RequestSpecificValues.Current_Item.Behaviors.Dark_Flag, (short) current_mask, RequestSpecificValues.Current_Item.Behaviors.Main_Thumbnail);
                            }
                        }
                    }
                }
            }

            // Set the code for bib level mets to show the volume tree by default
            if ((RequestSpecificValues.Current_Item.METS_Header.RecordStatus_Enum == METS_Record_Status.BIB_LEVEL) && (String.IsNullOrEmpty(RequestSpecificValues.Current_Mode.ViewerCode)))
            {
                RequestSpecificValues.Current_Mode.ViewerCode = "allvolumes1";
            }

            // If there is a file name included, look for the sequence of that file
            if (!String.IsNullOrEmpty(RequestSpecificValues.Current_Mode.Page_By_FileName))
            {
                int page_sequence = RequestSpecificValues.Current_Item.Divisions.Physical_Tree.Page_Sequence_By_FileName(RequestSpecificValues.Current_Mode.Page_By_FileName);
                if (page_sequence > 0)
                {
                    RequestSpecificValues.Current_Mode.ViewerCode = page_sequence.ToString();
                    RequestSpecificValues.Current_Mode.Page = (ushort) page_sequence;
                }
            }

            // Get the valid viewer code
            RequestSpecificValues.Tracer.Add_Trace("Item_HtmlSubwriter.Add_Controls", "Getting the appropriate item viewer");

            if (( String.IsNullOrEmpty(RequestSpecificValues.Current_Mode.ViewerCode)) && ( !String.IsNullOrEmpty(RequestSpecificValues.Current_Mode.Coordinates)))
            {
                RequestSpecificValues.Current_Mode.ViewerCode = "map";
            }
            int currentPageIndex = RequestSpecificValues.Current_Mode.Page.HasValue ? RequestSpecificValues.Current_Mode.Page.Value : 1;
            RequestSpecificValues.Current_Mode.ViewerCode = RequestSpecificValues.Current_Item.Web.Get_Valid_Viewer_Code(RequestSpecificValues.Current_Mode.ViewerCode, currentPageIndex );
            View_Object viewObject = RequestSpecificValues.Current_Item.Web.Get_Viewer(RequestSpecificValues.Current_Mode.ViewerCode);
            PageViewer = ItemViewer_Factory.Get_Viewer(viewObject, RequestSpecificValues.Current_Item.Bib_Info.SobekCM_Type_String.ToUpper(), RequestSpecificValues.Current_Item, RequestSpecificValues.Current_User, RequestSpecificValues.Current_Mode);

            // If this was in fact restricted by IP address, restrict now
            if (itemRestrictedFromUserByIp)
            {
                if ((PageViewer==null)||((PageViewer.ItemViewer_Type != ItemViewer_Type_Enum.Citation) &&
                    (PageViewer.ItemViewer_Type != ItemViewer_Type_Enum.MultiVolume) &&
                    (PageViewer.ItemViewer_Type != ItemViewer_Type_Enum.Related_Images)))
                {
                    PageViewer = new Restricted_ItemViewer(Item_Restricted_Message);
                    RequestSpecificValues.Current_Mode.ViewerCode = "res";
                }
            }

            // If execution should end, do it now
            if (RequestSpecificValues.Current_Mode.Request_Completed)
                return;

            RequestSpecificValues.Tracer.Add_Trace("Html_MainWriter.Add_Controls", "Created " + PageViewer.GetType().ToString().Replace("SobekCM.Library.ItemViewer.Viewers.", ""));

            // Assign the rest of the information, if a page viewer was created
            if (PageViewer != null)
            {
                PageViewer.CurrentItem = RequestSpecificValues.Current_Item;
                PageViewer.CurrentMode = RequestSpecificValues.Current_Mode;
                PageViewer.Translator = UI_ApplicationCache_Gateway.Translation;
                PageViewer.CurrentUser = RequestSpecificValues.Current_User;

                // Special code if this is the citation viewer
                Citation_ItemViewer viewer = PageViewer as Citation_ItemViewer;
                if (viewer != null)
                {
                    viewer.Code_Manager = UI_ApplicationCache_Gateway.Aggregations;
                    viewer.Item_Restricted = itemRestrictedFromUserByIp;
                }

                // Special code if this is the multi-volumes viewer
                var itemViewer = PageViewer as MultiVolumes_ItemViewer;
                if (itemViewer != null)
                {
                    if (RequestSpecificValues.Items_In_Title == null)
                    {
                        // Look in the cache first
                        RequestSpecificValues.Items_In_Title = CachedDataManager.Retrieve_Items_In_Title(RequestSpecificValues.Current_Item.BibID, RequestSpecificValues.Tracer);

                        // If still null, try to pull from the database
                        if (RequestSpecificValues.Items_In_Title == null)
                        {
                            // Get list of information about this item group and save the item list
                            DataSet itemDetails = Engine_Database.Get_Item_Group_Details(RequestSpecificValues.Current_Item.BibID, RequestSpecificValues.Tracer);
                            RequestSpecificValues.Items_In_Title = new SobekCM_Items_In_Title(itemDetails.Tables[1]);

                            //// Add the related titles, if there are some
                            //if ((currentGroup.Tables.Count > 3) && (currentGroup.Tables[3].Rows.Count > 0))
                            //{
                            //    foreach (DataRow thisRow in currentGroup.Tables[3].Rows)
                            //    {
                            //        string relationship = thisRow["Relationship"].ToString();
                            //        string title = thisRow["GroupTitle"].ToString();
                            //        string bibid = thisRow["BibID"].ToString();
                            //        string link_and_title = "<a href=\"" + currentMode.Base_URL + bibid + "<%URL_OPTS%>\">" + title + "</a>";
                            //        RequestSpecificValues.Current_Item.Behaviors.All_Related_Titles.Add(new SobekCM.Resource_Object.Behaviors.Related_Titles(relationship, link_and_title));
                            //    }
                            //}

                            // Store in cache if retrieved
                            if (RequestSpecificValues.Items_In_Title != null)
                            {
                                CachedDataManager.Store_Items_In_Title(RequestSpecificValues.Current_Item.BibID, RequestSpecificValues.Items_In_Title, RequestSpecificValues.Tracer);
                            }
                        }
                    }

                    itemViewer.Item_List = RequestSpecificValues.Items_In_Title;
                }

                // Finally, perform any necessary work before display
                PageViewer.Perform_PreDisplay_Work(RequestSpecificValues.Tracer);

                // Get the list of any special behaviors
                behaviors = PageViewer.ItemViewer_Behaviors;
            }
            else
            {
                behaviors = new List<HtmlSubwriter_Behaviors_Enum>();
            }

            // ALways suppress the banner and skip to main content
            if (behaviors == null)
                behaviors = new List<HtmlSubwriter_Behaviors_Enum>();

            if (!behaviors.Contains(HtmlSubwriter_Behaviors_Enum.Suppress_Banner))
                behaviors.Add(HtmlSubwriter_Behaviors_Enum.Suppress_Banner);
            if (!behaviors.Contains(HtmlSubwriter_Behaviors_Enum.Include_Skip_To_Main_Content_Link))
                behaviors.Add(HtmlSubwriter_Behaviors_Enum.Include_Skip_To_Main_Content_Link);

            //if ((searchMatchOnThisPage) && ((PageViewer.ItemViewer_Type == ItemViewer_Type_Enum.JPEG) || (PageViewer.ItemViewer_Type == ItemViewer_Type_Enum.JPEG2000)))
            //{
            //    if (PageViewer.ItemViewer_Type == ItemViewer_Type_Enum.JPEG2000)
            //    {
            //        Aware_JP2_ItemViewer jp2_viewer = (Aware_JP2_ItemViewer) PageViewer;
            //        jp2_viewer.Add_Feature("Red", "DrawEllipse", ((int) (featureXRatioLocation*jp2_viewer.Width)), ((int) (featureYRatioLocation*jp2_viewer.Height)), 800, 800);

            //    }
            //}
        }
        /// <summary> Constructor for a new instance of the Item_HtmlSubwriter class </summary>
        /// <param name="Current_Item">Current item to display </param>
        /// <param name="Current_Page"> Current page within the item</param>
        /// <param name="Current_User"> Currently logged on user for determining rights over this item </param>
        /// <param name="Code_Manager"> List of valid collection codes, including mapping from the Sobek collections to Greenstone collections</param>
        /// <param name="Translator"> Language support object which handles simple translational duties </param>
        /// <param name="Show_TOC"> Flag indicates whether to show the table of contents open for this item </param>
        /// <param name="Show_Zoomable"> Flag indicates if the zoomable server is available </param>
        /// <param name="Current_Mode"> Mode / navigation information for the current request</param>
        /// <param name="Current_Collection"> Current item aggregation this item is being displayed from (if there is one) </param>
        /// <param name="Item_Restricted_Message"> Message to be shown because this item is restriced from the current user by IP address </param>
        /// <param name="Items_In_Title"> List of items within a title (for item group display in particular) </param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering </param>
        public Item_HtmlSubwriter(SobekCM_Item Current_Item, Page_TreeNode Current_Page, User_Object Current_User,
                                  Aggregation_Code_Manager Code_Manager,
                                  Language_Support_Info Translator, bool Show_TOC, bool Show_Zoomable,
                                  SobekCM_Navigation_Object Current_Mode,
                                  Item_Aggregation Current_Collection,
                                  string Item_Restricted_Message,
                                  SobekCM_Items_In_Title Items_In_Title,
                                  Custom_Tracer Tracer )
        {
            Mode = Current_Mode;
            currentUser = Current_User;
            currentItem = Current_Item;
            currentPage = Current_Page;
            itemsInTitle = Items_In_Title;
            translations = Translator;
            showToc = Show_TOC;
            showZoomable = Show_Zoomable;
            Hierarchy_Object = Current_Collection;
            Nav_Bar_Menu_Section_Added = false;
            itemCheckedOutByOtherUser = false;
            userCanEditItem = false;
            searchResultsCount = 0;

            // Determine if this item is an EAD
            isEadTypeItem = (currentItem.Get_Metadata_Module(GlobalVar.EAD_METADATA_MODULE_KEY) != null);

            // Determine if this item is actually restricted
            itemRestrictedFromUserByIp = false;
            if (Item_Restricted_Message.Length > 0)
                itemRestrictedFromUserByIp = true;

            // If this item is restricted by IP than alot of the upcoming code is unnecessary
            if (!itemRestrictedFromUserByIp)
            {
                // Searching for EAD/EAC type items is different from others
                if (!isEadTypeItem)
                {
                    // If there is a coordinate search, and polygons, do that
                    // GEt the geospatial metadata module
                    GeoSpatial_Information geoInfo = currentItem.Get_Metadata_Module(GlobalVar.GEOSPATIAL_METADATA_MODULE_KEY) as GeoSpatial_Information;
                    if ((geoInfo != null) && (geoInfo.hasData))
                    {
                        if ((currentMode.Coordinates.Length > 0) && (geoInfo.Polygon_Count > 1))
                        {
                            // Determine the coordinates in this search
                            string[] splitter = currentMode.Coordinates.Split(",".ToCharArray());

                            if (((splitter.Length > 1) && (splitter.Length < 4)) || ((splitter.Length == 4) && (splitter[2].Length == 0) && (splitter[3].Length == 0)))
                            {
                                Double.TryParse(splitter[0], out providedMaxLat);
                                Double.TryParse(splitter[1], out providedMaxLong);
                                providedMinLat = providedMaxLat;
                                providedMinLong = providedMaxLong;
                            }
                            else if (splitter.Length >= 4)
                            {
                                Double.TryParse(splitter[0], out providedMaxLat);
                                Double.TryParse(splitter[1], out providedMaxLong);
                                Double.TryParse(splitter[2], out providedMinLat);
                                Double.TryParse(splitter[3], out providedMinLong);
                            }

                            // Now, if there is length, determine the count of results
                            searchResultsString = new List<string>();
                            if (searchResultsString.Count > 0)
                            {
                                searchResultsCount = searchResultsString.Count;

                                // Also, look to see where the current point lies in the matching, current polygon
                                if ((providedMaxLong == providedMinLong) && (providedMaxLat == providedMinLat))
                                {
                                    foreach (Coordinate_Polygon itemPolygon in geoInfo.Polygons)
                                    {
                                        // Is this the current page?
                                        if (itemPolygon.Page_Sequence == currentMode.Page)
                                        {
                                            if (itemPolygon.is_In_Bounding_Box(providedMaxLat, providedMaxLong))
                                            {
                                                searchMatchOnThisPage = true;
                                                ReadOnlyCollection<Coordinate_Point> boundingBox = itemPolygon.Bounding_Box;
                                                featureYRatioLocation = Math.Abs(((providedMaxLat - boundingBox[0].Latitude)/(boundingBox[0].Latitude - boundingBox[1].Latitude)));
                                                featureXRatioLocation = Math.Abs(((providedMaxLong - boundingBox[0].Longitude)/(boundingBox[0].Longitude - boundingBox[1].Longitude)));
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                // Determine if this user can edit this item
                if (currentUser != null)
                {
                    userCanEditItem = currentUser.Can_Edit_This_Item(currentItem);
                }

                // Is this a postback?
                if ((currentMode.isPostBack) && ( currentUser != null))
                {
                    // Handle any actions from standard user action (i.e., email, add to bookshelf, etc.. )
                    if (HttpContext.Current.Request.Form["item_action"] != null)
                    {
                        string action = HttpContext.Current.Request.Form["item_action"].ToLower().Trim();

                        if (action == "email")
                        {
                            string address = HttpContext.Current.Request.Form["email_address"].Replace(";", ",").Trim();
                            string comments = HttpContext.Current.Request.Form["email_comments"].Trim();
                            string format = HttpContext.Current.Request.Form["email_format"].Trim().ToUpper();
                            if (address.Length > 0)
                            {
                                // Determine the email format
                                bool is_html_format = !(format == "TEXT");

                                // CC: the user, unless they are already on the list
                                string cc_list = currentUser.Email;
                                if (address.ToUpper().IndexOf(currentUser.Email.ToUpper()) >= 0)
                                    cc_list = String.Empty;

                                // Send the email
                                HttpContext.Current.Session.Add("ON_LOAD_MESSAGE", !Item_Email_Helper.Send_Email(address, cc_list, comments, currentUser.Full_Name,currentMode.SobekCM_Instance_Abbreviation,currentItem,is_html_format,HttpContext.Current.Items["Original_URL"].ToString())
                                    ? "Error encountered while sending email" : "Your email has been sent");

                                HttpContext.Current.Response.Redirect( HttpContext.Current.Items["Original_URL"].ToString(), false);
                            }
                        }

                        if (action == "add_item")
                        {
                            string usernotes = HttpContext.Current.Request.Form["add_notes"].Trim();
                            string foldername = HttpContext.Current.Request.Form["add_bookshelf"].Trim();
                            bool open_bookshelf = HttpContext.Current.Request.Form["open_bookshelf"] != null;

                            if (SobekCM_Database.Add_Item_To_User_Folder(currentUser.UserID, foldername, currentItem.BibID, currentItem.VID, 0, usernotes, Tracer))
                            {
                                currentUser.Add_Bookshelf_Item(currentItem.BibID, currentItem.VID);

                                // Ensure this user folder is not sitting in the cache
                                Cached_Data_Manager.Remove_User_Folder_Browse(currentUser.UserID, foldername, Tracer);

                                HttpContext.Current.Session.Add("ON_LOAD_MESSAGE", "Item was saved to your bookshelf.");

                                if (open_bookshelf)
                                {
                                    HttpContext.Current.Session.Add("ON_LOAD_WINDOW", "?m=lmfl" + foldername.Replace("\"", "%22").Replace("'", "%27").Replace("=", "%3D").Replace("&", "%26") + "&vp=1");
                                }
                            }
                            else
                            {
                                HttpContext.Current.Session.Add("ON_LOAD_MESSAGE", "ERROR encountered while trying to save to your bookshelf.");
                            }

                            HttpContext.Current.Response.Redirect(HttpContext.Current.Items["Original_URL"].ToString(), false);
                        }

                        if (action == "remove")
                        {
                            if (SobekCM_Database.Delete_Item_From_User_Folders(currentUser.UserID, currentItem.BibID, currentItem.VID, Tracer))
                            {
                                currentUser.Remove_From_Bookshelves(currentItem.BibID, currentItem.VID);
                                Cached_Data_Manager.Remove_All_User_Folder_Browses(currentUser.UserID, Tracer);
                                HttpContext.Current.Session.Add("ON_LOAD_MESSAGE", "Item was removed from your bookshelves.");
                            }
                            else
                            {
                                HttpContext.Current.Session.Add("ON_LOAD_MESSAGE", "ERROR encountered while trying to remove item from your bookshelves.");
                            }

                            HttpContext.Current.Response.Redirect(HttpContext.Current.Items["Original_URL"].ToString(), false);
                        }

                        if (action.IndexOf("add_tag") == 0)
                        {
                            int tagid = -1;
                            if (action.Replace("add_tag", "").Length > 0)
                            {
                                tagid = Convert.ToInt32(action.Replace("add_tag_", ""));
                            }
                            string description = HttpContext.Current.Request.Form["add_tag"].Trim();
                            int new_tagid = SobekCM_Database.Add_Description_Tag(currentUser.UserID, tagid, currentItem.Web.ItemID, description, Tracer);
                            if (new_tagid > 0)
                            {
                                currentItem.Behaviors.Add_User_Tag(currentUser.UserID, currentUser.Full_Name, description, DateTime.Now, new_tagid);
                                currentUser.Has_Descriptive_Tags = true;
                            }

                            HttpContext.Current.Response.Redirect(HttpContext.Current.Items["Original_URL"].ToString(), false);
                        }

                        if (action.IndexOf("delete_tag") == 0)
                        {
                            if (action.Replace("delete_tag", "").Length > 0)
                            {
                                int tagid = Convert.ToInt32(action.Replace("delete_tag_", ""));
                                if (currentItem.Behaviors.Delete_User_Tag(tagid, currentUser.UserID))
                                {
                                    SobekCM_Database.Delete_Description_Tag(tagid, Tracer);
                                }
                            }
                            HttpContext.Current.Response.Redirect(HttpContext.Current.Items["Original_URL"].ToString(), false);
                        }
                    }
                }

                // Handle any request from the internal header for the item
                if ((HttpContext.Current != null) && (HttpContext.Current.Request.Form["internal_header_action"] != null) && ( currentUser != null ))
                {
                    // Pull the action value
                    string internalHeaderAction = HttpContext.Current.Request.Form["internal_header_action"].Trim();

                    // Was this to save the item comments?
                    if (internalHeaderAction == "save_comments")
                    {
                        string new_comments = HttpContext.Current.Request.Form["intheader_internal_notes"].Trim();
                        if ( Resource_Object.Database.SobekCM_Database.Save_Item_Internal_Comments( currentItem.Web.ItemID, new_comments))
                            currentItem.Tracking.Internal_Comments = new_comments;
                    }

                    // Is this to change accessibility?
                    if ((internalHeaderAction == "public") || (internalHeaderAction == "private") || (internalHeaderAction == "restricted"))
                    {
                        int current_mask = currentItem.Behaviors.IP_Restriction_Membership;
                        switch (internalHeaderAction)
                        {
                            case "public":
                                currentItem.Behaviors.IP_Restriction_Membership = 0;
                                break;

                            case "private":
                                currentItem.Behaviors.IP_Restriction_Membership = -1;
                                break;

                            case "restricted":
                                currentItem.Behaviors.IP_Restriction_Membership = 1;
                                break;
                        }

                        // Save the new visibility
                        if (currentItem.Behaviors.IP_Restriction_Membership != current_mask)
                        {
                            if (Resource_Object.Database.SobekCM_Database.Set_IP_Restriction_Mask(currentItem.Web.ItemID, currentItem.Behaviors.IP_Restriction_Membership, currentUser.UserName, String.Empty))
                            {
                                Cached_Data_Manager.Remove_Digital_Resource_Object(currentItem.BibID, currentItem.VID, Tracer);
                                Cached_Data_Manager.Store_Digital_Resource_Object(currentItem.BibID, currentItem.VID, currentItem, Tracer);
                            }
                        }
                    }
                }
            }

            // Set the code for bib level mets to show the volume tree by default
            if ((currentItem.METS_Header.RecordStatus_Enum == METS_Record_Status.BIB_LEVEL) && (currentMode.ViewerCode.Length == 0))
            {
                currentMode.ViewerCode = "allvolumes1";
            }

            // If there is a file name included, look for the sequence of that file
            if (currentMode.Page_By_FileName.Length > 0)
            {
                int page_sequence = currentItem.Divisions.Physical_Tree.Page_Sequence_By_FileName(currentMode.Page_By_FileName);
                if (page_sequence > 0)
                {
                    currentMode.ViewerCode = page_sequence.ToString();
                    currentMode.Page = (ushort) page_sequence;
                }
            }

            // Get the valid viewer code
            Tracer.Add_Trace("Html_MainWriter.Add_Controls", "Getting the appropriate item viewer");

            if ((currentMode.ViewerCode.Length == 0) && (currentMode.Coordinates.Length > 0))
            {
                currentMode.ViewerCode = "map";
            }
            currentMode.ViewerCode = currentItem.Web.Get_Valid_Viewer_Code(currentMode.ViewerCode, currentMode.Page);
            View_Object viewObject = currentItem.Web.Get_Viewer(currentMode.ViewerCode);
            PageViewer = ItemViewer_Factory.Get_Viewer(viewObject, currentItem.Bib_Info.SobekCM_Type_String.ToUpper());

            // If this was in fact restricted by IP address, restrict now
            if (itemRestrictedFromUserByIp)
            {
                if ((PageViewer.ItemViewer_Type != ItemViewer_Type_Enum.Citation) &&
                    (PageViewer.ItemViewer_Type != ItemViewer_Type_Enum.MultiVolume) &&
                    (PageViewer.ItemViewer_Type != ItemViewer_Type_Enum.Related_Images))
                {
                    PageViewer = new Restricted_ItemViewer(Item_Restricted_Message);
                    currentMode.ViewerCode = "res";
                }
            }

            Tracer.Add_Trace("Html_MainWriter.Add_Controls", "Created " + PageViewer.GetType().ToString().Replace("SobekCM.Library.ItemViewer.Viewers.", ""));

            // Assign the rest of the information, if a page viewer was created
            if (PageViewer != null)
            {
                PageViewer.CurrentItem = currentItem;
                PageViewer.CurrentMode = currentMode;
                PageViewer.Translator = Translator;
                PageViewer.CurrentUser = currentUser;

                if (PageViewer is Citation_ItemViewer)
                {

                    ((Citation_ItemViewer)PageViewer).Code_Manager = Code_Manager;
                    ((Citation_ItemViewer)PageViewer).Current_User = Current_User;
                    ((Citation_ItemViewer)PageViewer).Item_Restricted = itemRestrictedFromUserByIp;
                }

                // The JPEG2000 viewer should always include the nav bar to include the navigation thumbnail image
                if (PageViewer is Aware_JP2_ItemViewer)
                {
                    Nav_Bar_Menu_Section_Added = true;
                }

                //if (page_viewer is ItemViewer.Viewers.Google_Map_ItemViewer)
                //{
                //    ((ItemViewer.Viewers.Google_Map_ItemViewer)page_viewer).Matching_Tiles_List = search_results_string;
                //}

                if (PageViewer is MultiVolumes_ItemViewer)
                {
                    if (itemsInTitle == null)
                    {
                        // Look in the cache first
                        itemsInTitle = Cached_Data_Manager.Retrieve_Items_In_Title(currentItem.BibID, Tracer);

                        // If still null, try to pull from the database
                        if (itemsInTitle == null)
                        {
                            // Get list of information about this item group and save the item list
                            DataSet itemDetails = SobekCM_Database.Get_Item_Group_Details(currentItem.BibID, Tracer);
                            itemsInTitle = new SobekCM_Items_In_Title(itemDetails.Tables[1]);

                            //// Add the related titles, if there are some
                            //if ((currentGroup.Tables.Count > 3) && (currentGroup.Tables[3].Rows.Count > 0))
                            //{
                            //    foreach (DataRow thisRow in currentGroup.Tables[3].Rows)
                            //    {
                            //        string relationship = thisRow["Relationship"].ToString();
                            //        string title = thisRow["GroupTitle"].ToString();
                            //        string bibid = thisRow["BibID"].ToString();
                            //        string link_and_title = "<a href=\"" + currentMode.Base_URL + bibid + "<%URL_OPTS%>\">" + title + "</a>";
                            //        currentItem.Behaviors.All_Related_Titles.Add(new SobekCM.Resource_Object.Behaviors.Related_Titles(relationship, link_and_title));
                            //    }
                            //}

                            // Store in cache if retrieved
                            if (itemsInTitle != null)
                            {
                                Cached_Data_Manager.Store_Items_In_Title(currentItem.BibID, itemsInTitle, Tracer);
                            }
                        }
                    }

                    ((MultiVolumes_ItemViewer)PageViewer).Item_List = itemsInTitle;
                }

                // Finally, perform any necessary work before display
                PageViewer.Perform_PreDisplay_Work(Tracer);
            }

            if ((searchMatchOnThisPage) && ((PageViewer.ItemViewer_Type == ItemViewer_Type_Enum.JPEG) || (PageViewer.ItemViewer_Type == ItemViewer_Type_Enum.JPEG2000)))
            {
                if (PageViewer.ItemViewer_Type == ItemViewer_Type_Enum.JPEG2000)
                {
                    Aware_JP2_ItemViewer jp2_viewer = (Aware_JP2_ItemViewer)PageViewer;
                    jp2_viewer.Add_Feature("Red", "DrawEllipse", ((int)(featureXRatioLocation * jp2_viewer.Width)), ((int)(featureYRatioLocation * jp2_viewer.Height)), 800, 800);
                }

            }
        }