public DocumentItemData Clone()
        {
            DocumentItemData temp = new DocumentItemData();

            temp.DocumentId            = this.DocumentId;
            temp.DocumentThumbnailPath = this.DocumentThumbnailPath;
            temp.AnnotationsFilePath   = this.AnnotationsFilePath;
            temp.Title = this.Title;
            temp.Date  = this.Date;

            return(temp);
        }
        public static LEADDocument ReplaceDocument(string oldDocumentID, List <string> newDocumentFiles, ObservableCollection <DocumentItemData> documentsCollection, int oldDocumentIndex, out Exception error)
        {
            error = null;
            var items = documentsCollection.Where(x => x.DocumentId.Equals(oldDocumentID));

            if (items == null || items.Count() == 0)
            {
                error = new Exception($"No document found with ID {oldDocumentID}");
                return(null);
            }

            DocumentItemData oldItemData = items.ElementAt(0);

            DateTime        oldDocumentDate    = oldItemData.Date;
            string          oldDocumentTitle   = oldItemData.Title;
            bool            oldIsSelectedState = oldItemData.IsSelected;
            OcrOutputFormat oldDocumentFormat  = oldItemData.DocumentFormat;

            List <Exception> errors            = null;
            LEADDocument     convertedDocument = CreateDocument(newDocumentFiles, null, null, out errors);

            if (convertedDocument != null && File.Exists(newDocumentFiles[0]))
            {
                OcrOutputFormat format = GetDocumentFormatFromExt(newDocumentFiles[0]);
                SaveDocument(convertedDocument, documentsCollection, format, oldDocumentIndex);

                items = documentsCollection.Where(x => x.DocumentId.Equals(convertedDocument.DocumentId));
                DocumentItemData newItemData = null;
                if (items != null && items.Count() > 0)
                {
                    newItemData = items.ElementAt(0);
                    // Keep the old item name and date since we are sorting documents by date and we don't want to change the converted item position.
                    newItemData.Date       = oldDocumentDate;
                    newItemData.Title      = oldDocumentTitle;
                    newItemData.IsSelected = oldIsSelectedState;

                    // Update the document files inside the "Documents" folder of this item in order to delete them later when we convert this document to another format.
                    newItemData.DocumentFiles = new List <string>(newDocumentFiles);
                    SerializeDocuments(documentsCollection);
                }

                // Delete the old document from cache and create new LEADDocument out of the converted file and replace the converted item in the documents list.
                DeleteFromCache(oldDocumentID);

                // Delete the old document files that built this document object from the "Documents" folder.
                if (newItemData != null && oldItemData.DocumentFiles != null && oldItemData.DocumentFiles.Count > 0)
                {
                    foreach (string docFile in oldItemData.DocumentFiles)
                    {
                        try
                        {
                            if (!newItemData.DocumentFiles.Contains(docFile) && File.Exists(docFile))
                            {
                                File.Delete(docFile);
                            }
                        }
                        catch (Exception) { }
                    }
                }
            }
            else
            {
                if (errors != null && errors.Count > 0)
                {
                    error = errors[0];
                }
            }

            return(convertedDocument);
        }
        public static void SaveDocument(LEADDocument document, ObservableCollection <DocumentItemData> documentsCollection, OcrOutputFormat format = OcrOutputFormat.None, int replaceItemAtIndex = -1, bool autoSerializeDocuments = true)
        {
            string thumbnailPath = Path.Combine(CacheDirectory, document.DocumentId, $"thumbnail.jpeg");

            // Create new document item data
            DateTime currentDatetime = DateTime.Now;

            if (string.IsNullOrWhiteSpace(document.Name))
            {
                if (replaceItemAtIndex == -1) // we are adding new document and not replacing existing one, so use the old document name
                {
                    document.Name = FindUniqueDocumentName(documentsCollection);
                }
                else
                {
                    document.Name = documentsCollection[replaceItemAtIndex].Title;
                }
            }

            string annotationsFilePath = Path.Combine(ApplicationDirectory, "Documents", $"{document.Name}.xml");

            DocumentItemData newDocumentItemData = new DocumentItemData();

            newDocumentItemData.DocumentId            = document.DocumentId;
            newDocumentItemData.DocumentThumbnailPath = thumbnailPath;
            newDocumentItemData.AnnotationsFilePath   = annotationsFilePath;
            newDocumentItemData.Title          = document.Name;
            newDocumentItemData.Date           = currentDatetime;
            newDocumentItemData.DocumentFormat = format;

            if (Device.RuntimePlatform == Device.iOS)
            {
                // Save the original file path that was loaded from gallery, so we can delete it later when we convert this document in
                // order to save space since we won't need this file anymore.
                // only do this for the newly created documents and not the already converted ones.
                if (format == OcrOutputFormat.None)
                {
                    newDocumentItemData.DocumentFiles = GetDocumentSourceFiles(document);
                }
            }

            IEnumerable <DocumentItemData> items = documentsCollection.Where(x => x.DocumentId.Equals(document.DocumentId));

            if ((items != null && items.Count() > 0) || replaceItemAtIndex != -1)
            {
                // Document already exist, so just update it
                int index = (replaceItemAtIndex != -1) ? replaceItemAtIndex : documentsCollection.IndexOf(items.ElementAt(0));
                documentsCollection.Insert(index, newDocumentItemData);
                documentsCollection.RemoveAt(index + 1);
            }
            else
            {
                documentsCollection.Add(newDocumentItemData);
            }

            if (autoSerializeDocuments)
            {
                SerializeDocuments(documentsCollection);
            }

            document.SaveToCache();

            if (document.Pages != null && document.Pages.Count > 0)
            {
                using (var codecs = new RasterCodecs())
                {
                    try
                    {
                        LeadSize thumbnailSize = LeadSize.Create((int)(document.Images.ThumbnailPixelSize.Width * 1.5), (int)(document.Images.ThumbnailPixelSize.Height * 1.5));
                        using (var rasterImage = document.Pages[0].GetImage())
                        {
                            var thumbnailImage = rasterImage.CreateThumbnail(thumbnailSize.Width, thumbnailSize.Height, 32, RasterViewPerspective.TopLeft, RasterSizeFlags.Bicubic);
                            if (thumbnailImage == null)
                            {
                                thumbnailImage = document.Pages[0].GetThumbnailImage();
                            }
                            codecs.Save(thumbnailImage, thumbnailPath, RasterImageFormat.Jpeg, 0);
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                        codecs.Save(document.Pages[0].GetThumbnailImage(), thumbnailPath, RasterImageFormat.Jpeg, 0);
                    }
                }
            }
        }