internal static string[] CacheMoviesSection
            (IMLSection section)
        {
            MainImportingEngine.CurrentProgress = 0;
            MainImportingEngine.ThisProgress.Progress
                (MainImportingEngine.CurrentProgress,
                "Caching Movies section...");


            int[] itemIDs = section != null
                         ?  section.GetAllItemIDs()
                         :  new int[]
            {
            };


            int itemsCount = itemIDs.Length;

            string[] filmLocations = new string[itemsCount];
            int      cacheCounter  = 0;


            foreach (IMLItem item in itemIDs.Select
                         (id => section != null ? section.FindItemByID(id) : null))
            {
                filmLocations[cacheCounter]
                    = item.Location;

                cacheCounter++;
            }

            return(filmLocations);
        }
        internal static void ImportMeePopupProviderField(IMLSection section)
        {

            if (!Settings.MeePopupProviderCompatibility)
                return;

            #region Process initialization feedback
            MainImportingEngine.ThisProgress.Progress(0, "Adding field meePopupProvider...");
            Thread.Sleep(300);
            #endregion

            section.AddNewTag("meePopupProvider");
      
            var itemsProcessed = 0; 

            section.BeginUpdate();
 
            #region Update Section items 
            foreach (var readOnlyItem in section.GetReadOnlyItems()) 
            { 
                string id = readOnlyItem.ID.ToString(CultureInfo.InvariantCulture);
 
                #region Calculate progress
                int percentComplete = (int)(itemsProcessed * (100.0 / section.ItemCount ) ); 
                if (percentComplete > 100) 
                    percentComplete = 100;

                itemsProcessed++;
 
                #endregion

                #region Poll for user cancellation request
                if (!MainImportingEngine.ThisProgress.Progress(percentComplete, "Processing Items")) 
                { 
                    section.CancelUpdate(); 
                    MainImportingEngine.ThisProgress.Progress(100, "Import Canceled");
                    return;
                }
                #endregion

                #region If field is populated, continue to next item
                if ( (string) readOnlyItem.Tags.Get("meePopupProvider", "") == id)
                    continue;
                #endregion

                #region Populate the item's field
                IMLItem item = section.FindItemByID(readOnlyItem.ID); 
                item.Tags["meePopupProvider"] = id; 
                item.SaveTags();
                #endregion

            } //endof foreach
            #endregion

            section.EndUpdate();
        } //endof function
        internal static bool UpdateSectionItem(int itemId, IMLSection section,
            string pluginpath, ref int currentItem,
            int totalItems, string[] videoExtensions,
            string[] videoExtensionsCommon)
        {
            Helpers.LogMessageToFile("Calculating import progress...");
            ImportProgress.CurrentProgress =
            ImportProgress.CalculateImportProgress
                (currentItem, totalItems);

            #region item variables

            Helpers.LogMessageToFile("Locating item by ID: " + itemId);
            var item = section.FindItemByID(itemId);

            if (item == null)
                return true;

            Helpers.LogMessageToFile("Section entry was verified.");
            Helpers.LogMessageToFile("Initializing item keys...");

            string location = item.Location;
            string fileExtension;

            #endregion

            string rootDirectory;

            if ( !RetrieveFileInfo
                (location, out rootDirectory,
                out fileExtension) )
                return true;

            if ( !Diagnostics.FileTypeVerifier.FileIsVideo
                (videoExtensions, fileExtension, videoExtensionsCommon) )
                return true;

            VideoHashConstructor.VideoFingerprintIdentifier.RetrieveFileHash
                    (item, location);

            if (ImportProgress.UserCancels(ImportProgress.SpecialStatus, item))
                return false;

            VideoSubtitleDownloaderHelpers.
                SearchForAndDownloadSubtitleForPrimaryOrSecondaryLanguage(item);

            if (ImportProgress.UserCancels(ImportProgress.SpecialStatus, item))
                return false;

            item.SaveTags();
            currentItem++;

            return true;
        }
        internal static string[] CacheMoviesSection(IMLSection section)
        {
            MainImportingEngine.CurrentProgress = 0;
            MainImportingEngine.ThisProgress.Progress
                (MainImportingEngine.CurrentProgress,
                "Caching Movies section...");

            int[] itemIDs = section != null
                         ?  section.GetAllItemIDs()
                         :  new int[] { };

            int itemsCount = itemIDs.Length;
            string[] filmLocations = new string[itemsCount];
            int cacheCounter = 0;

            foreach (IMLItem item in itemIDs.Select
                (id => section != null ? section.FindItemByID(id) : null))
            {

                filmLocations[cacheCounter]
                    = item.Location;

                cacheCounter++;

            }

            return filmLocations;
        }
                internal static bool UpdateFilmItem
                    (int itemID,
                     IMLSection moviesSection,
                     string pluginpath,
                     ref int currentItem,
                     int totalItems,
                     IBaseSystem iBaseSystem,
                     IEnumerable<string> combinedSceneTags)
                {



                    MainImportingEngine
                        .CurrentProgress =
                        ImportingEngineHelpers
                        .ComputeProgress
                        (currentItem, totalItems);




                    #region item variables


                    Helpers.UpdateProgress("", "Fetching library item...");
                    Debugger.LogMessageToFile( "Fetching library item...");


                    var item = moviesSection
                        .FindItemByID(itemID);

                    if (item == null)
                        return true;


                    DirectoryInfo parent;


                    string moviehash,
                        imdbid,
                        tmdbID,
                        year,
                        itemTitle,
                        sortTitle,
                        location;



                    SingleMovieItemUpdaterHelpers.InitializeItemKeys
                        (itemID, item, out moviehash, out imdbid,
                         out tmdbID, out year, out itemTitle,
                         out sortTitle, out location);


                

                    #endregion



                    Helpers.UpdateProgress("", "Creating filesystem instance...");

                    Debugger.LogMessageToFile(String.Format
                        ("Creating filesystem instances for media file {0}...",
                        location));


                    try
                    {


                        var fi = new FileInfo
                            (location);

                        parent = fi.Directory;


                    }
                    catch (Exception e)
                    {

                        Debugger.LogMessageToFile(String.Format
                            ("Unable to create filesystem instances" +
                             " for this media file." +
                             "An error occured: {0}", e));

                        return true;
                                                            
                    }





                    if (IdentifyFilmAndDownloadMetadata
                        (combinedSceneTags,
                        item, parent))
                        return true;


                    if (Helpers.UserCancels
                        (MainImportingEngine.SpecialStatus))
                        return false;



                    SetFilmItemProcessingFlags
                        .SetUpdateFlag(item);


                    item.SaveTags();
                    currentItem++;
                    return true;

                }
        internal static bool UpdateFilmItem
            (int itemID, IMLSection moviesSection,
             IMLItemList allFilmItems, 
             ref bool fileServerChecked,
             ref bool fileServerIsOnline, 
             ConnectionResult connectionresult,
             IMDbOperations imdbOp, string pluginpath,
             ref int currentItem, int totalItems,
             string mdfSettingsa, IBaseSystem ibs,
             IEnumerable<string> combinedSceneTags) 
        {


            MainImportingEngine.CurrentProgress 
                = ImportingEngineHelpers
                .ComputeProgress
                (currentItem, totalItems);




            #region Pre-updaters

            IMLItem item
                = moviesSection
                .FindItemByID(itemID);

            if (item == null)
                return true;

            MainImportingEngine.SpecialStatus
                = "Updating " + item.Name + "...";

            Debugger.LogMessageToFile
                (Environment.NewLine +
                "Starting to work with library item:" +
                 " " + item.Name +" with ID: " + itemID);


            Debugger.LogMessageToFile
                ("Initializing item variables...");


            string imdbid = Helpers.GetTagValueFromItem(item, "ImdbID");
            string tmdbID = Helpers.GetTagValueFromItem(item, "TMDbID");

            string filmYear = Helpers.GetTagValueFromItem(item, "Year");
            string itemTitle = Helpers.GetTagValueFromItem(item, "Title");
            string sortTitle = Helpers.GetTagValueFromItem(item, "SortTitle");


            bool isMultipart = false;
            string location = item.Location;
            string[] multipart = null;
            bool isUNC = false;

            DirectoryInfo parent;
            DirectoryInfo root;
            string videoFilename;


            MultipartFilmLibraryItemDetector
                .DetectMultipartItemRetrieveFirstItemLocation
                (ref location, ref isMultipart, ref multipart);


            if (!FilmItemUpdaterHelpers
                .RetrievePathLocations
                (location, out videoFilename,
                out parent, out root))
                return false;


            bool updateFilmItem;
            if (FilmItemUpdaterHelpers
                .PerformPreupdatingDiagnostics
                (moviesSection, ref fileServerChecked, 
                ref fileServerIsOnline, root, location, 
                item, ref isUNC, out updateFilmItem))
                return updateFilmItem;

            #endregion




            #region Primary Updating

            Debugger.LogMessageToFile
                ("Identification of film '"
                + itemTitle + "' is complete." +
                 " Continuing to download online data.");


            if (Helpers.GetTagValueFromItem
                (item, "MediaFairy-processed") != "--processed--")
            {

                #region Identifiers

                bool b;
                if (FilmItemUpdaterHelpers.ExtractLocalMetadataForFilmItem
                    (fileServerIsOnline, ref imdbOp,
                    pluginpath, combinedSceneTags,
                    parent, isUNC, item,
                    ref imdbid, out b))
                    return b;


                imdbOp.ImdbMovie = null;
                imdbOp.ImdbId = imdbid;


                //#region Set IsExactMatched flag for the video fingerprint uploader

                //try
                //{
                //    Year = Helpers.GetTagValueFromItem(Item, "Year");
                //}
                //catch
                //{
                //}

                //if (!String.IsNullOrEmpty(Year))
                //    isExactMatched = true;

                //if (!String.IsNullOrEmpty(imdbid))
                //    isExactMatched = true;

                //#endregion

                if (Helpers.UserCancels
                    (MainImportingEngine
                    .SpecialStatus, item))
                    return false;


                if (
                    !VideoFingerprintIdentifier
                    .VideoFingerprintIdentifier
                    .IdentifyVideo(ref imdbid, 
                    ref tmdbID, ref imdbOp,
                    item, fileServerIsOnline,
                    isUNC, location, parent.FullName,
                    filmYear, connectionresult, moviesSection)
                    )
                {

                    Debugger.LogMessageToFile
                        ("Unable to identify this video. Continuing to next item.");
                    return true;

                }
                Debugger.LogMessageToFile
                    ("Video identification was succesfull!");


                if (Helpers.UserCancels
                    (MainImportingEngine.SpecialStatus, item))
                    return false;


                

                #endregion


                #region Set Updating Flags




                #endregion


                #region extract important fields for online searches

                string imdbidTmp = Helpers.GetTagValueFromItem(item, "ImdbID");

                #region Get IMDbID

                if (!String.IsNullOrEmpty(imdbidTmp))
                {
                    imdbid = Helpers.GetTagValueFromItem(item, "ImdbID");
                    imdbOp.ImdbId = Helpers.GetTagValueFromItem(item, "ImdbID");
                }
                else
                {
                    if (!String.IsNullOrEmpty(imdbOp.ImdbId))
                        imdbid = imdbOp.ImdbId;
                    else imdbOp.ImdbId = imdbid;

                    item.Tags["ImdbID"] = imdbOp.ImdbId;
                }

                //MessageBox.Show("Item tag imdbid: " + Helpers.GetTagValueFromItem(Item,"ImdbID"]);

                #endregion

                #region Get ItemTitle

                itemTitle = Helpers.GetTagValueFromItem(item, "Title");

                if (String.IsNullOrEmpty(itemTitle))
                {
                    if (!String.IsNullOrEmpty(item.Name))
                    {
                        itemTitle = item.Name;
                    }
                    else return true;
                }

                #endregion

                #endregion

                #region Metadata Downloaders

                //MessageBox.Show("Can work online:" + connectionresult.CanWorkOnline);

                if (connectionresult.InternetConnectionAvailable
                    || !Settings.ConnectionDiagnosticsEnabled)
                {



                        #region download details


                       imdbid = FilmItemUpdaterHelpers.IMDbDetailer
                           (moviesSection, imdbOp,
                           item, itemTitle, imdbid);
                        


                    OSoperations.GetDetailsFromOSdb
                        (imdbid, item, connectionresult.OSDbIsOnline,
                        !imdbOp.NotListed);
    

                    #endregion


                        if (Helpers.UserCancels
                            (MainImportingEngine
                            .SpecialStatus, item))
                            return false;


                        #region Get ItemTitle

                        if (!String.IsNullOrEmpty(Helpers.GetTagValueFromItem(item, "Title")))
                        {
                            itemTitle = Helpers.GetTagValueFromItem(item, "Title");
                        }
                        else if (!String.IsNullOrEmpty(item.Name))
                        {
                            itemTitle = item.Name;
                        }
                        else return true;

                        #endregion

                        #region Set SortTitle

                        if (!String.IsNullOrEmpty
                            (itemTitle) 
                            && String.IsNullOrEmpty
                            (sortTitle))
                        {
                            if (itemTitle.StartsWith("The"))
                            {
                                sortTitle = itemTitle.Remove(0, 4) + ", The ";
                                Debugger.LogMessageToFile
                                    ("Set item's SortTitle to: '" + sortTitle + "'.");
                            }
                            else sortTitle = itemTitle;

                            item.Tags["SortTitle"] = sortTitle;
                            item.SaveTags();
                        }

                        #endregion



                    if (!FilmItemUpdaterHelpers
                            .DownloadFilmDetailsExtra(item))
                            return false;


                    location = FilmItemUpdaterHelpers
                            .PerformFilmOrganizing
                            (fileServerChecked, fileServerIsOnline,
                            connectionresult, currentItem, itemTitle,
                            multipart, location, isMultipart, item);


                    if (Helpers.UserCancels
                            (MainImportingEngine
                            .SpecialStatus, item))
                            return false;


                        //MovieDescriptorWriter
                        //    .WriteMovieDescriptor
                        //    (item, itemTitle, imdbid, 
                        //    parent.FullName,
                        //    fileServerIsOnline, isUNC);



                        if (Helpers.UserCancels
                            (MainImportingEngine
                            .SpecialStatus, item))
                            return false;



                        if (!DownloadFilmCoverAndBakdropArt
                            (fileServerIsOnline, mdfSettingsa, 
                            ibs, item, isUNC, itemTitle, location,
                            parent, videoFilename))
                            return false;


                }

                #endregion
            }

            #endregion




            if (!FilmItemSecondaryUpdater
                .PerformSecondaryFilmItemUpdating
                (moviesSection, allFilmItems, item))
                return false;



            item.SaveTags();
            currentItem++;

            return true;

        }
        internal static bool UpdateFilmItem
            (int itemID,
            IMLSection moviesSection,
            string pluginpath,
            ref int currentItem,
            int totalItems,
            IBaseSystem iBaseSystem,
            IEnumerable <string> combinedSceneTags)
        {
            MainImportingEngine
            .CurrentProgress =
                ImportingEngineHelpers
                .ComputeProgress
                    (currentItem, totalItems);



            #region item variables


            Helpers.UpdateProgress("", "Fetching library item...");
            Debugger.LogMessageToFile("Fetching library item...");


            var item = moviesSection
                       .FindItemByID(itemID);

            if (item == null)
            {
                return(true);
            }


            DirectoryInfo parent;


            string moviehash,
                   imdbid,
                   tmdbID,
                   year,
                   itemTitle,
                   sortTitle,
                   location;



            SingleMovieItemUpdaterHelpers.InitializeItemKeys
                (itemID, item, out moviehash, out imdbid,
                out tmdbID, out year, out itemTitle,
                out sortTitle, out location);



            #endregion



            Helpers.UpdateProgress("", "Creating filesystem instance...");

            Debugger.LogMessageToFile(String.Format
                                          ("Creating filesystem instances for media file {0}...",
                                          location));


            try
            {
                var fi = new FileInfo
                             (location);

                parent = fi.Directory;
            }
            catch (Exception e)
            {
                Debugger.LogMessageToFile(String.Format
                                              ("Unable to create filesystem instances" +
                                              " for this media file." +
                                              "An error occured: {0}", e));

                return(true);
            }



            if (IdentifyFilmAndDownloadMetadata
                    (combinedSceneTags,
                    item, parent))
            {
                return(true);
            }


            if (Helpers.UserCancels
                    (MainImportingEngine.SpecialStatus))
            {
                return(false);
            }



            SetFilmItemProcessingFlags
            .SetUpdateFlag(item);


            item.SaveTags();
            currentItem++;
            return(true);
        }
        internal static void ImportPcGames(IMLImportProgress progress, IMLSection gamesSection)
        {

            if ((!Settings.EnableGamesUpdater && !Settings.EnableGamesImporter))
                return;
                            
            if (String.IsNullOrEmpty(Settings.GameShortcutsLocation) )
                return;

            if ( !File.Exists(Settings.GameShortcutsLocation) )
            return;


            Importer.ThisProgress = progress;
            //Importer.GeneralStatus = "Updating Games Section";
            Importer.SpecialStatus = String.Empty;
            Importer.ThisProgress.Progress(Importer.CurrentProgress, "Updating Games Section...");

            DirectoryInfo pcGamesFolder = new DirectoryInfo(Settings.GameShortcutsLocation);
            FileInfo[] shortcuts = pcGamesFolder.GetFiles("*.lnk", SearchOption.AllDirectories);
            //IMLSection GamesSection = Importer.library.FindSection("Games", true);

            #region Man importing engine

            int itemCounter = 0;
            WshShell shell = new WshShellClass();

            gamesSection.BeginUpdate();

            foreach (FileInfo shortcut in shortcuts)
            {
                int progressStep = 100 / shortcuts.Length;
                Importer.CurrentProgress = 100 - (progressStep * (shortcuts.Length - itemCounter));

                ImportPcGame(shell, shortcut.FullName, gamesSection);
                itemCounter++;
            }

            gamesSection.EndUpdate();

            #endregion

            #region Update

            if (!Settings.EnableGamesUpdater) return;


           

            gamesSection.BeginUpdate();
            itemCounter = 0;
            int[] allItemIDs = gamesSection.GetAllItemIDs();

            foreach (int id in allItemIDs)
            {
                IMLItem item = gamesSection.FindItemByID(id);
                int progressStep = 100 / allItemIDs.Length;
                Importer.CurrentProgress = 100 - (progressStep * (allItemIDs.Length - itemCounter));
                Downloaders.DownloadGameDetailsFromMobyGames(item);

                Helpers.UserCancels(Importer.SpecialStatus, item);

                itemCounter++;
            }

            gamesSection.EndUpdate();
            
            

            #endregion

        } //endof function
        //TODO: Refactor BackupMediaSection Method
        public static bool LibrarySynchronizerBackupMediaSection
            (IMLSection section, string xmlDirectory)
        {

            string xmlFilename = section.Name + ".xml";

            #region Construct XML file path
            string xmlPath;

            if (xmlDirectory.EndsWith("\\"))
                xmlPath = xmlDirectory + xmlFilename;
            else
                xmlPath = xmlDirectory + "\\" + xmlFilename;

            #endregion
            

            try
            {

                #region create basic structure
                MainImportingEngine.ThisProgress.Progress(MainImportingEngine.CurrentProgress, "Creating backup for section " + section.Name + "...");
                Thread.Sleep(1000);
                // Create the xml document container
                XmlDocument doc = new XmlDocument();
                // Create the XML Declaration, and append it to XML document
                XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", null, null);
                doc.AppendChild(dec);
                //Create the root element
                XmlElement root = doc.CreateElement("Library");
                doc.AppendChild(root);
                #endregion

                bool alreadyShowedError = false;
                foreach (int id in section.GetAllItemIDs())
                {
                    // Create Film structure
                    XmlElement item = doc.CreateElement("item");
                    IMLItem Item = section.FindItemByID(id);

                    #region Read key tags
                    XmlElement name = doc.CreateElement("name");
                    name.InnerText = Item.Name;
                    item.AppendChild(name);

                    XmlElement location = doc.CreateElement("location");
                    location.InnerText = Item.Location;
                    item.AppendChild(location);
                    #endregion

                    #region Read the rest of the tags
                    foreach (string TagName in (string[])section.GetTagNames())
                    {
                        if (TagName.Contains(" ") && !alreadyShowedError)
                        {
                            //StatusForm.statusForm.TrayIcon.ShowBalloonTip(5000, "Invalid Tag Name", "The tag '" + TagName + "' in your " + Section.Name + " section contains one or more space characters. Tags with space characters are invalid for xml files. For this reason, the tag's name will be saved with those characters removed. Please note however that if this tag was created by another plugin or a script, said plugin will not be able to read this tag in case you restore your library. Please report this issue to the plugin's developer, in order to be acknowledged and fixed.", ToolTipIcon.Error);
                            //Thread.Sleep(5000);
                            alreadyShowedError = true;
                        }

                        string elementName = TagName.Replace(" ", "");
                        XmlElement element = doc.CreateElement(elementName);
                        element.InnerText = Helpers.GetTagValueFromItem(Item, TagName);
                        item.AppendChild(element);
                    }
                    #endregion

                    root.AppendChild(item);
                }

                #region Finalize and save xml file           
                //string xmlOutput = doc.OuterXml;
                try
                {
                    doc.Save(xmlPath);
                    //File.WriteAllText(xmlpath, xmlOutput);
                }
                catch (Exception e)
                {
                    Debugger.LogMessageToFile("Unable to save an xml backup of your media section to: " + xmlPath + ". The error was: " + e );
                    //StatusForm.statusForm.TrayIcon.ShowBalloonTip(10000, "Access to a media directory was rectricted", "MediaFairy could not write a Section backup XML file in the directory " + xmlDirectory + " because Windows security privileges do not allow modification for this directory.", ToolTipIcon.Warning);
                    //Thread.Sleep(2000);
                    return false;
                }
                #endregion


            }
            catch (Exception e)
            {
                StatusForm.statusForm.TrayIcon.ShowBalloonTip(10000, "Error writing XML backup", "An unexpected error ocurred while trying to save an XML backup of your media sections. Please see Debug.log for details.", ToolTipIcon.Error);
                Debugger.LogMessageToFile("An unexpected error ocurred while trying to save an XML backup of a media section. The error was: " + e);
                return false;
            }

            return true;
        }