protected internal static int HandleChainedByTagFile(EnhancedFileInfo chain, 
             EnhancedFileInfo newElement)
        {
            MLTag location = new MLTag("Location", chain.Item.Location);

            int fileIndex =
                location.Values.Select(value => value.ToLowerInvariant()).ToList().IndexOf(
                    newElement.FileInformation.FullName.ToLowerInvariant());

            MLTag externalID = new MLTag("ExternalID", chain.Item.ExternalID);

            if (fileIndex >= 0)
            {
                location.Values[fileIndex] = newElement.Item.Location;
                chain.Item.Location = location.Value;
                externalID.Values[fileIndex] = newElement.Item.ExternalID;
                chain.Item.ExternalID = externalID.Value;
            }
            else
            {
                location.Values.Add(newElement.Item.Location);
                location.Values.Sort();
                chain.Item.Location = location.Value;
                externalID.Values.Add(newElement.Item.ExternalID);
                externalID.Values.Sort();
                chain.Item.ExternalID = externalID.Value;
            }

            return fileIndex;
        }
 public EnhancedFileInfo Query(IMLItem item)
 {
     if (this.files.Keys.Contains(item))
     {
         this.RetrivedItemWasCached = true;
         return this.files[item];
     }
     else
     {
         MLTag location = new MLTag("Location", item.Location);
         EnhancedFileInfo file = new EnhancedFileInfo(new FileInfo(location.Values[0])) { Item = item };
         this.Add(file);
         this.RetrivedItemWasCached = false;
         return file;
     }
 }
        internal static void DeleteNonExistentItems(TheImport theImport)
        {
            theImport.RelocatedFiles = new List<string>();
            theImport.DeletedFiles = 0;

            int oldItemCount
                = theImport.Importer
                .Section.ItemCount;

            for (int itemPos = oldItemCount - 1; itemPos >= 0; itemPos--)
            {

                IMLItem item
                    = theImport.Importer
                    .Section[itemPos];

                bool itemChanged = false;

                var locationTag
                    = new MLTag
                        ("Location",
                        item.Location);

                int percentage = (itemPos * 10) / oldItemCount;

                string logMessage1 =
                    "      Checking item: ID="
                    + item.ID
                    + " Location="
                    + locationTag.Value;

                if (!theImport.CheckProgress
                    (percentage, logMessage1))
                {
                    return;
                }

                theImport.Importer.LogMessages
                    .Enqueue(new LogMessage
                        ("Info", logMessage1));

                for (int filePos = locationTag.Values.Count - 1; filePos >= 0; filePos--)
                {

                    if (!theImport.CanDelete(locationTag.Values[filePos]))
                        continue;

                    if (!theImport.Relocate(locationTag, filePos))
                    {
                        string logMessage2 = "Removing " + locationTag.Values[filePos] + " from item's location";
                        theImport.Importer.LogMessages.Enqueue(new LogMessage("Info", logMessage2));
                        locationTag.Values.RemoveAt(filePos);
                    }

                    itemChanged = true;
                }

                if (locationTag.Values.Count == 0)
                {
                    theImport.Importer.Section.DeleteItem(item);
                    theImport.Importer.LogMessages.Enqueue(new LogMessage("Info", "Item deleted"));
                    theImport.DeletedFiles++;
                }
                else
                {
                    if (itemChanged)
                    {
                        item.Location = locationTag.Value;
                        item.ExternalID = locationTag.Value.ToLower();
                        item.SaveTags();
                    }

                }

            }
        }
        internal static void ScanExistingItems(TheImport theImport)
        {
            IMLItemList oldItems
                = theImport.Importer
                .Section.GetReadOnlyItems();

            int oldItemCount = oldItems.Count;

            const string logMessage1
                = "Prescanning existing items:";

            if (!theImport
                .CheckProgress
                (0, logMessage1))
            {
                return;
            }

            bool createItemsChainedByTagCache
                = (theImport.Importer
                .ChainingOption
                == ChainOption.ChainByTags)
                &&   (theImport.Importer
                .TagsToChainBy.Length > 0);

            for (int itemPos = 0; itemPos < oldItemCount; itemPos++)
            {
                IMLItem item = oldItems[itemPos];
                var locationTag = new MLTag("Location", item.Location);

                foreach (string location in locationTag.Values)
                {

                    if (theImport.Location2Id.Keys.Contains
                        (location.ToLowerInvariant()))
                        continue;

                    string logMessage2 = "Mapped the location " + location  + " to the itemid " + item.ID;
                    int percentage = (itemPos * 10) / oldItemCount;
                    if (!theImport.CheckProgress(percentage, logMessage2))
                    {
                        return;
                    }

                    theImport.Location2Id.Add(location.ToLowerInvariant(), item.ID);
                }

                if (!createItemsChainedByTagCache)
                    continue;

                IMLItem writableItem
                    = theImport.Importer.Section
                        .FindItemByID(item.ID);

                IMLItem cachedItem
                    = theImport.ItemsChainedByTagCache
                        .Query(writableItem);

                if (cachedItem == writableItem)
                    continue;

                string logMessage4
                    = "You are chaining by tags " +
                      "but the item (ID: " + item.ID
                      + " Location: "
                      + item.Location
                      + ") has the same values" +
                      " for the tags you're chaining" +
                      " by as the item (ID: "
                      +  cachedItem.ID
                      + " Location: "
                      + cachedItem.Location + ").";

                theImport.Importer.LogMessages.Enqueue
                    (new LogMessage
                         ("Warn", logMessage4));

            }
        }
        internal static void HandleChainedFile(RootFolderHandlerBase rootFolderHandlerBase,
             EnhancedFileInfo theFile, 
             EnhancedFileInfo previousFile)
        {
            if ((!rootFolderHandlerBase.IsNewItem)
                && (!rootFolderHandlerBase.Update))
            {
                return;
            }

            var location = new MLTag
                ("item_location",
                previousFile.Item.Location);

            location.Values.Add(theFile.FileInformation.FullName);

            location.Values.Sort();

            previousFile.Item.Location = location.Value;

            previousFile.Item.ExternalID
                = previousFile.Item.Location.ToLower();

            if (rootFolderHandlerBase.Importer.FileSize)
            {
                previousFile.Item.Tags[rootFolderHandlerBase.Importer.FileSizeTagName] =
                    (long)previousFile.Item.Tags[rootFolderHandlerBase.Importer.FileSizeTagName] + theFile.FileInformation.Length;
            }

            if (rootFolderHandlerBase.Importer.CreationDate)
            {
                object creationDate = previousFile.Item.Tags[rootFolderHandlerBase.Importer.CreationDateTagName];
                if (creationDate is string)
                {
                    if (!String.IsNullOrEmpty((string)creationDate))
                    {
                        if (String.CompareOrdinal(theFile.FileInformation.CreationTime.ToString("yyyy-MM-dd hh:mm:ss"), (string)creationDate) < 0)
                        {
                            previousFile.Item.Tags[rootFolderHandlerBase.Importer.CreationDateTagName] = theFile.FileInformation.CreationTime.ToString("yyyy-MM-dd hh:mm:ss");
                        }
                    }
                }
            }

            if (rootFolderHandlerBase.Importer.LastAccessDate)
            {

                object lastAccessDate = previousFile.Item.Tags[rootFolderHandlerBase.Importer.LastAccessDateTagName];

                if (lastAccessDate is string)
                {
                    if (!String.IsNullOrEmpty((string)lastAccessDate))
                    {
                        if (String.CompareOrdinal(theFile.FileInformation.LastAccessTime.ToString("yyyy-MM-dd hh:mm:ss"), (string)lastAccessDate) > 0)
                        {
                            previousFile.Item.Tags[rootFolderHandlerBase.Importer.LastAccessDateTagName] = theFile.FileInformation.LastAccessTime.ToString("yyyy-MM-dd hh:mm:ss");
                        }
                    }
                }
            }

            if (!rootFolderHandlerBase
                .Importer.LastModificationDate)
                return;

            object lastModificationDate
                = previousFile.Item.Tags
                [rootFolderHandlerBase
                .Importer.LastModificationDateTagName];

            var modificationDate = lastModificationDate as string;

            if (modificationDate == null)
                return;

            if (String.IsNullOrEmpty
                (modificationDate))
                return;

            if (String.CompareOrdinal
                (theFile.FileInformation
                    .LastWriteTime.ToString
                    ("yyyy-MM-dd hh:mm:ss"),
                    modificationDate) <= 0)
                return;

            previousFile.Item.Tags
                [rootFolderHandlerBase
                .Importer.LastModificationDateTagName]
                = theFile.FileInformation
                .LastWriteTime.ToString
                ("yyyy-MM-dd hh:mm:ss");
        }
        internal bool Relocate(MLTag location, int pos)
        {
            if (Importer.RootFolders.Length > 1)
            {

                string oldRootFolder = string.Empty;

                foreach (string rootFolder in Importer.RootFolders)
                {
                    if (location.Values[pos].StartsWith(rootFolder))
                    {
                        oldRootFolder = rootFolder;
                    }
                }

                if (oldRootFolder.Equals(string.Empty))
                {
                    return false;
                }

                string filename
                    = location.Values[pos]
                    .Substring(oldRootFolder.Length);

                var possibleLocations = new List<string>();

                foreach (string rootFolder in Importer.RootFolders)
                {
                    if (!rootFolder.Equals(oldRootFolder))
                    {
                        possibleLocations.Add(rootFolder + filename);
                    }
                }

                foreach (string possibleLocation in possibleLocations)
                {
                    if (!File.Exists(possibleLocation))
                        continue;

                    string logMessage = "Found " + location.Values[pos] + " at new location: " + possibleLocation;
                    this.Importer.LogMessages.Enqueue(new LogMessage("Info", logMessage));
                    location.Values[pos] = possibleLocation;
                    this.RelocatedFiles.Add(possibleLocation);
                    return true;
                }
            }

            return false;
        }
        public void LinkImages(EnhancedFileInfo file, ImageSearchOptions searchOptions)
        {
            this.LogMessages.Enqueue(new LogMessage("Info", "  Searching images"));
            if (searchOptions.ImageTagName.Length > 0)
            {
                file.Item.Tags[searchOptions.ImageTagName] = string.Empty;
            }
            if (searchOptions.ImageTagName.Length == 0 || searchOptions.SaveInImageBaseTag)
            {
                file.Item.ImageFile = string.Empty;
            }

            List<string> imagePaths = new List<string>();
            EnhancedFileInfo tmpFile = file;
            string[] parameter =
                searchOptions.ImageFolderSearchPattern.Split(';').Select(mask => MLItem.EvaluateTagValues(mask, tmpFile.Item)).
                    ToArray();
            string evaluatedImageFileMasks = string.Join(":", parameter);
            this.LogMessages.Enqueue(new LogMessage("Info", "    in the image folder"));
            imagePaths.AddRange(this.CachedImages.Query(searchOptions.ImageFolder, evaluatedImageFileMasks));
            bool shouldSearchInFileFolder = (searchOptions.SearchFileFolderOptions == "Always".Translate()) ||
                                            ((searchOptions.SearchFileFolderOptions ==
                                             "When no linked files in links rootfolder".Translate()) && (imagePaths.Count == 0));
            if (shouldSearchInFileFolder)
            {
                string[] parameter2 =
                    searchOptions.FileFolderSearchPattern.Split(';').Select(
                        mask => MLItem.EvaluateTagValues(mask, tmpFile.Item)).ToArray();
                evaluatedImageFileMasks = string.Join(":", parameter2);
                this.LogMessages.Enqueue(new LogMessage("Info", "    in the files folder"));
                imagePaths.AddRange(
                    this.CachedImages.Query(file.FileInformation.DirectoryName, evaluatedImageFileMasks));
            }

            if ((searchOptions.MaxImages > 0) && (imagePaths.Count > searchOptions.MaxImages))
            {
                imagePaths.RemoveRange(searchOptions.MaxImages, imagePaths.Count - searchOptions.MaxImages);
            }

            if (imagePaths.Count > 0)
            {
                this.LogMessages.Enqueue(new LogMessage("Info", "    Writing image tag(s)"));
                MLTag imageFile = new MLTag("ImageFile", string.Empty);
                foreach (string image in imagePaths)
                {
                    imageFile.Values.Add(image);
                }

                if (searchOptions.ImageTagName.Equals(string.Empty))
                {
                    file.Item.ImageFile = imageFile.Value;
                }
                else
                {
                    file.Item.Tags[searchOptions.ImageTagName] = imageFile.Value;
                    if (searchOptions.SaveInImageBaseTag)
                    {
                        file.Item.Tags["imagefile"] = imageFile.Values[0];
                        file.Item.ImageFile = imageFile.Values[0];
                    }
                }

                this.LogMessages.Enqueue(new LogMessage("Info", "    ..Done writing image tag(s)"));
            }
        }