/// <summary> Constructor for a new instance of the ManageMenu_ItemViewer class </summary>
        /// <param name="Current_Object"> Digital resource to display </param>
        /// <param name="Current_User"> Current user for this session </param>
        /// <param name="Current_Mode"> Navigation object which encapsulates the user's current request </param>
        public ManageMenu_ItemViewer(SobekCM_Item Current_Object, User_Object Current_User, SobekCM_Navigation_Object Current_Mode)
        {
            // Save the current user and current mode information (this is usually populated AFTER the constructor completes,
            // but in this case (QC viewer) we need the information for early processing
            CurrentMode = Current_Mode;
            CurrentUser = Current_User;
            CurrentItem = Current_Object;

            // Determine if this user can edit this item
            if (CurrentUser == null)
            {
                Current_Mode.ViewerCode = String.Empty;
                Current_Mode.Redirect();
                return;
            }
            else
            {
                bool userCanEditItem = CurrentUser.Can_Edit_This_Item(CurrentItem);
                if (!userCanEditItem)
                {
                    Current_Mode.ViewerCode = String.Empty;
                    Current_Mode.Redirect();
                    return;
                }
            }
        }
        /// <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="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="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 ShowToc, 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 = ShowToc;
            showZoomable = Show_Zoomable;
            Current_Aggregation = Current_Collection;
            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 = Item_Restricted_Message.Length > 0;

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

            // If this item is restricted by IP than alot of the upcoming code is unnecessary
            if (( currentUser != null ) && ((!itemRestrictedFromUserByIp) || ( userCanEditItem ) || ( currentUser.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 = 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)));
                //                            }
                //                        }
                //                    }
                //                }
                //            }
                //        }
                //    }
                //}

                #endregion

                // Is this a postback?
                if (currentMode.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 = 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(), currentUser.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();
                                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(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);
                            HttpContext.Current.ApplicationInstance.CompleteRequest();
                            Current_Mode.Request_Completed = true;
                            return;
                        }

                        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);
                            HttpContext.Current.ApplicationInstance.CompleteRequest();
                            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(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);
                            HttpContext.Current.ApplicationInstance.CompleteRequest();
                            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 (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);
                            HttpContext.Current.ApplicationInstance.CompleteRequest();
                            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) && ( 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;
                        }

                        // Is this new visibility different than the old one?
                        if (currentItem.Behaviors.IP_Restriction_Membership != current_mask)
                        {
                            // Save this to the database
                            if (Resource_Object.Database.SobekCM_Database.Set_IP_Restriction_Mask(currentItem.Web.ItemID, currentItem.Behaviors.IP_Restriction_Membership, currentUser.UserName, String.Empty))
                            {
                                // Update the cached item
                                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);

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

            // 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(), currentItem, currentUser, currentMode);

            // 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";
                }
            }

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

            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;

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

                // Special code if this is the multi-volumes viewer
                var itemViewer = PageViewer as MultiVolumes_ItemViewer;
                if (itemViewer != null)
                {
                    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);
                            }
                        }
                    }

                    itemViewer.Item_List = itemsInTitle;
                }

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

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

            // ALways suppress the banner
            behaviors.Add(HtmlSubwriter_Behaviors_Enum.Suppress_Banner);

            //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 QC_ItemViewer class </summary>
        /// <param name="Current_Object"> Digital resource to display </param>
        /// <param name="Current_User"> Current user for this session </param>
        /// <param name="Current_Mode"> Navigation object which encapsulates the user's current request </param>
        public QC_ItemViewer(SobekCM_Item Current_Object, User_Object Current_User, SobekCM_Navigation_Object Current_Mode)
        {
            // Save the current user and current mode information (this is usually populated AFTER the constructor completes,
            // but in this case (QC viewer) we need the information for early processing
            CurrentMode = Current_Mode;
            CurrentUser = Current_User;

            //Assign the current resource object to qc_item
            qc_item = Current_Object;
            //Save to the User's session
            HttpContext.Current.Session[Current_Object.BibID + "_" + Current_Object.VID + " QC Work"] = qc_item;

            // If there is no user, send to the login
            if (CurrentUser == null)
            {
                CurrentMode.Mode = Display_Mode_Enum.My_Sobek;
                CurrentMode.My_Sobek_Type = My_Sobek_Type_Enum.Logon;
                CurrentMode.Redirect();
                return;
            }

            // If the user cannot edit this item, go back
            if (!CurrentUser.Can_Edit_This_Item(Current_Object))
            {
                CurrentMode.ViewerCode = String.Empty;
                CurrentMode.Redirect();
                return;
            }

            //If there are no pages for this item, redirect to the image upload screen
            if (qc_item.Web.Static_PageCount == 0)
            {
                CurrentMode.Mode = Display_Mode_Enum.My_Sobek;
                CurrentMode.My_Sobek_Type = My_Sobek_Type_Enum.Page_Images_Management;
                CurrentMode.Redirect();
                return;
            }

            // Get the links for the METS
            string greenstoneLocation = Current_Object.Web.Source_URL + "/";
            complete_mets = greenstoneLocation + Current_Object.BibID + "_" + Current_Object.VID + ".mets.xml";

            // MAKE THIS USE THE FILES.ASPX WEB PAGE if this is restricted (or dark)
            if ((Current_Object.Behaviors.Dark_Flag) || (Current_Object.Behaviors.IP_Restriction_Membership > 0))
            {
                complete_mets = CurrentMode.Base_URL + "files/" + qc_item.BibID + "/" + qc_item.VID + "/" + qc_item.BibID + "_" + qc_item.VID + ".mets.xml";
            }

            // Get the special qc_item, which matches the passed in Current_Object, at least the first time.
            // If the QC work is already in process, we may find a temporary METS file to read.

            // Determine the in process directory for this
            userInProcessDirectory = SobekCM_Library_Settings.In_Process_Submission_Location + "\\" + Current_User.UserName.Replace(".", "").Replace("@", "") + "\\qcwork\\" + qc_item.METS_Header.ObjectID;
            if (Current_User.ShibbID.Trim().Length > 0)
                userInProcessDirectory = SobekCM_Library_Settings.In_Process_Submission_Location + "\\" + Current_User.ShibbID + "\\qcwork\\" + qc_item.METS_Header.ObjectID;

            // Make the folder for the user in process directory
            if (!Directory.Exists(userInProcessDirectory))
                Directory.CreateDirectory(userInProcessDirectory);

            // Create the name for the tempoary METS file?
            metsInProcessFile = userInProcessDirectory + "\\" + Current_Object.BibID + "_" + Current_Object.VID + ".mets.xml";

            // Is this work in the user's SESSION state?
            qc_item = HttpContext.Current.Session[Current_Object.BibID + "_" + Current_Object.VID + " QC Work"] as SobekCM_Item;
            if (qc_item == null)
            {

                // Is there a temporary METS for this item, which is not expired?
                if ((File.Exists(metsInProcessFile)) &&
                    (File.GetLastWriteTime(metsInProcessFile).Subtract(DateTime.Now).Hours < 8))
                {
                    // Read the temporary METS file, and use that to build the qc_item
                    qc_item = SobekCM_Item_Factory.Get_Item(metsInProcessFile, Current_Object.BibID, Current_Object.VID, null, null, null);
                    qc_item.Source_Directory = Current_Object.Source_Directory;
                }
                else
                {
                    // Just read the normal otherwise ( if we had the ability to deep copy a SobekCM_Item, we could skip this )
                    qc_item = SobekCM_Item_Factory.Get_Item(Current_Object.BibID, Current_Object.VID, null, null, null);
                }

                // Save to the session, so it is easily available for next time
                HttpContext.Current.Session[Current_Object.BibID + "_" + Current_Object.VID + " QC Work"] = qc_item;
            }

            // If no QC item, this is an error
            if (qc_item == null)
            {
                throw new ApplicationException("Unable to retrieve the item for Quality Control in QC_ItemViewer.Constructor");
            }

            // Get the default QC profile
            qc_profile = QualityControl_Configuration.Default_Profile;

            title = "Quality Control";

            // If this was a post-back keep the required height and width for the qc area
            allThumbnailsOuterDiv1Width = -1;
            allThumbnailsOuterDiv1Height = -1;
            string temp_width = HttpContext.Current.Request.Form["QC_window_width"] ?? String.Empty;
            string temp_height = HttpContext.Current.Request.Form["QC_window_height"] ?? String.Empty;

            if ((temp_width.Length > 0) && (temp_height.Length > 0))
            {
                // Parse the values and save to the session
                if (Int32.TryParse(temp_width, out allThumbnailsOuterDiv1Width))
                    HttpContext.Current.Session["QC_AllThumbnailsWidth"] = allThumbnailsOuterDiv1Width;
                if (Int32.TryParse(temp_height, out allThumbnailsOuterDiv1Height))
                    HttpContext.Current.Session["QC_AllThumbnailsHeight"] = allThumbnailsOuterDiv1Height;

            }
            else
            {
                object session_width = HttpContext.Current.Session["QC_AllThumbnailsWidth"];
                if (session_width != null)
                    allThumbnailsOuterDiv1Width = (int) session_width;
                object session_height = HttpContext.Current.Session["QC_AllThumbnailsHeight"];
                if (session_height != null)
                    allThumbnailsOuterDiv1Height = (int) session_height;
            }

            // See if there were hidden requests
            hidden_request = HttpContext.Current.Request.Form["QC_behaviors_request"] ?? String.Empty;
            hidden_main_thumbnail = HttpContext.Current.Request.Form["Main_Thumbnail_File"] ?? String.Empty;
            hidden_move_relative_position = HttpContext.Current.Request.Form["QC_move_relative_position"] ?? String.Empty;
            hidden_move_destination_fileName = HttpContext.Current.Request.Form["QC_move_destination"] ?? String.Empty;
            autonumber_number_system = HttpContext.Current.Request.Form["Autonumber_number_system"] ?? String.Empty;
            string temp = HttpContext.Current.Request.Form["autonumber_mode_from_form"] ?? "0";
            Int32.TryParse(temp, out autonumber_mode_from_form);
            autonumber_text_only = HttpContext.Current.Request.Form["Autonumber_text_without_number"] ?? String.Empty;
            autonumber_number_only = HttpContext.Current.Request.Form["Autonumber_number_only"] ?? String.Empty;
            autonumber_number_system = HttpContext.Current.Request.Form["Autonumber_number_system"] ?? String.Empty;
            hidden_autonumber_filename = HttpContext.Current.Request.Form["Autonumber_last_filename"] ?? String.Empty;
            temp = HttpContext.Current.Request.Form["QC_sortable_option"] ?? "-1";
            if (Int32.TryParse(temp, out makeSortable) && (makeSortable > 0) && (makeSortable <= 3))
            {
                CurrentUser.Add_Setting("QC_ItemViewer:SortableMode",makeSortable);
            }
            temp = HttpContext.Current.Request.Form["QC_autonumber_option"] ?? "-1";
            if ((Int32.TryParse(temp, out autonumber_mode)) && ( autonumber_mode >= 0 ) && ( autonumber_mode <= 2 ))
            {
                CurrentUser.Add_Setting("QC_ItemViewer:AutonumberingMode", autonumber_mode);
            }

            //Get any notes/comments entered by the user
            notes = HttpContext.Current.Request.Form["txtComments"] ?? String.Empty;

            if (!(Int32.TryParse(HttpContext.Current.Request.Form["QC_Sortable"], out makeSortable))) makeSortable = 3;
            // If the hidden move relative position is BEFORE, it is before the very first page
            if (hidden_move_relative_position == "Before")
                hidden_move_destination_fileName = "[BEFORE FIRST]";

            try
            {

                //Call the JavaScript autosave function based on the option selected
                bool autosaveCacheValue = true;
                bool autosaveCache = false;

                //Conversion result of autosaveCacheValue(conversion successful or not) saved in autosaveCache

                if (HttpContext.Current.Session["autosave_option"] != null)
                    autosaveCache = bool.TryParse(HttpContext.Current.Session["autosave_option"].ToString(), out autosaveCacheValue);
                bool convert = bool.TryParse(HttpContext.Current.Request.Form["Autosave_Option"], out autosave_option);
                if (!convert && !autosaveCache)
                {
                    autosave_option = true;
                }
                else if (!convert && autosaveCache)
                {
                    autosave_option = autosaveCacheValue;
                }

                else
                {
                    HttpContext.Current.Session["autosave_option"] = autosave_option;
                }
            }
            catch (Exception e)
            {
                throw new ApplicationException("Error retrieving auto save option. " + e.Message);
            }

            // Check for a previously set main thumbnail, or one from the requesting form
            if (!String.IsNullOrEmpty(hidden_main_thumbnail))
            {
                HttpContext.Current.Session["main_thumbnail_" + qc_item.BibID + "_" + qc_item.VID] = hidden_main_thumbnail;
            }
            else if (HttpContext.Current.Session["main_thumbnail_" + qc_item.BibID + "_" + qc_item.VID] == null )
            {
                hidden_main_thumbnail = qc_item.Behaviors.Main_Thumbnail.Replace("thm.jpg", "");
                HttpContext.Current.Session["main_thumbnail_" + qc_item.BibID + "_" + qc_item.VID] = hidden_main_thumbnail;
            }
            else
            {
                hidden_main_thumbnail = HttpContext.Current.Session["main_thumbnail_" + qc_item.BibID + "_" + qc_item.VID].ToString();
            }

            //Get the list of associated errors for this item from the database
            int itemID = Resource_Object.Database.SobekCM_Database.Get_ItemID(Current_Object.BibID, Current_Object.VID);
            Get_QC_Errors(itemID);

            // Perform any requested actions
            switch (hidden_request)
            {
                case "autosave":
                case "save":
                case "complete":
                    //Save the current time
                    HttpContext.Current.Session["QC_timeUpdated"] = DateTime.Now.ToString("hh:mm tt");

                    // Read the data from the http form, perform all requests, and
                    // update the qc_item (also updates the session and temporary files)
                    // Save this updated information in the temporary folder's METS file for reading later if necessary.
                    if ((Save_From_Form_Request_To_Item(String.Empty, String.Empty)) && (( hidden_request == "save" ) || ( hidden_request == "complete")))
                    {
                        // If the user selected SAVE or COMPLETE, roll out the new version
                        Move_Temp_Changes_To_Production();

                        // Redirect differently depending on SAVE or COMPLETE
                        if (hidden_request == "save")
                        {
                            // Forward back to the QC form
                            HttpContext.Current.Response.Redirect(HttpContext.Current.Request.RawUrl, false);
                            HttpContext.Current.ApplicationInstance.CompleteRequest();
                            CurrentMode.Request_Completed = true;
                        }
                        else if (hidden_request == "complete")
                        {
                            // Forward to the item
                            CurrentMode.ViewerCode = String.Empty;
                            CurrentMode.Redirect();
                        }
                    }
                    break;

                case "cancel":
                    Cancel_Current_QC();

                    // Forward back to the default item view
                    CurrentMode.ViewerCode = String.Empty;
                    CurrentMode.Redirect();
                    break;

                case "clear_pagination":
                    ClearPagination();
                    HttpContext.Current.Response.Redirect(HttpContext.Current.Request.RawUrl, false);
                    HttpContext.Current.ApplicationInstance.CompleteRequest();
                    CurrentMode.Request_Completed = true;
                    break;

                case "clear_reorder":
                    Clear_Pagination_And_Reorder_Pages();
                    HttpContext.Current.Response.Redirect(HttpContext.Current.Request.RawUrl, false);
                    HttpContext.Current.ApplicationInstance.CompleteRequest();
                    CurrentMode.Request_Completed = true;
                    break;

                case "save_error":
                    string error_code = HttpContext.Current.Request.Form["QC_error_number"] ?? String.Empty;
                    string affected_page_index = HttpContext.Current.Request.Form["QC_affected_file"] ?? String.Empty;
                    SaveQcError(itemID,error_code, affected_page_index);
                    break;

                case "delete_page":
                    // Read the data from the http form, perform all requests, and
                    // update the qc_item (also updates the session and temporary files)
                    string filename_to_delete = HttpContext.Current.Request.Form["QC_affected_file"] ?? String.Empty;
                    if (Save_From_Form_Request_To_Item(String.Empty, filename_to_delete))
                    {
                        Delete_Resource_File(filename_to_delete);
                    }

                    // Since we deleted a page, we need to roll out our new version
                    Move_Temp_Changes_To_Production();

                    HttpContext.Current.Response.Redirect(HttpContext.Current.Request.RawUrl, false);
                    HttpContext.Current.ApplicationInstance.CompleteRequest();
                    CurrentMode.Request_Completed = true;
                    break;

                case "delete_selected_pages":
                    // Read the data from the http form, perform all requests, and
                    // update the qc_item (also updates the session and temporary files)
                    List<QC_Viewer_Page_Division_Info> selected_page_div_from_form;
                    if (Save_From_Form_Request_To_Item(String.Empty, String.Empty, out selected_page_div_from_form))
                    {
                        foreach (QC_Viewer_Page_Division_Info thisPage in selected_page_div_from_form)
                        {
                            Delete_Resource_File(thisPage.METS_StructMap_Page_Node.Files[0].File_Name_Sans_Extension);
                        }
                    }

                    // Since we deleted a page, we need to roll out our new version
                    Move_Temp_Changes_To_Production();

                    HttpContext.Current.Response.Redirect(HttpContext.Current.Request.RawUrl, false);
                    HttpContext.Current.ApplicationInstance.CompleteRequest();
                    CurrentMode.Request_Completed = true;
                    break;

                case "move_selected_pages":
                    // Read the data from the http form, perform all requests, and
                    // update the qc_item (also updates the session and temporary files)
                    Save_From_Form_Request_To_Item(hidden_move_destination_fileName, String.Empty);

                    HttpContext.Current.Response.Redirect(HttpContext.Current.Request.RawUrl, false);
                    HttpContext.Current.ApplicationInstance.CompleteRequest();
                    CurrentMode.Request_Completed = true;
                    break;
            }
        }