/**
         * Command actions
         */
        public void SaveBookmark(object input)
        {
            try
            {
                BookmarkRepo bookmarkRepo = new BookmarkRepo();

                // 0. Get old bookmark name
                _name = bookmarkRepo.GetBookmarkNameWithId(Bookmark.ID);

                // 1. Update new values to database
                bookmarkRepo.UpdateBookmark(Bookmark);

                // 1.1 Track bookmark update
                BookmarkInfo info = new BookmarkInfo(Bookmark.Name, User);
                new Tracker(User).TrackUpdate <BookmarkInfo>(info, _name);
            }
            catch (Exception e)
            {
                // Message = "constraint failed\r\nUNIQUE constraint failed: tblBookmark.Name, tblBookmark.UserID"}	System.Exception {System.Data.SQLite.SQLiteException}
                if (e.Message.Contains("UNIQUE"))
                {
                    if (
                        _dialogService.OpenDialog(new DialogYesNoViewModel("Bookmark with that name already exists, do you want to merge?", "Merge reference", DialogType.Question))
                        )
                    {
                        BookmarkRepo   repo         = new BookmarkRepo();
                        Bookmark       bookmarkFrom = repo.GetBookmark(_name, User);
                        Bookmark       bookmarkInto = repo.GetBookmark(Bookmark.Name, User);
                        List <Article> articlesFrom = repo.LoadArticlesForBookmark(User, bookmarkFrom);
                        List <Article> articlesInto = repo.LoadArticlesForBookmark(User, bookmarkInto);

                        // 1. Get unique articles between 2 references
                        List <Article> uniques = articlesFrom.Where(art => !articlesInto.Exists(el => el.Title == art.Title)).ToList();

                        // 2. Add those articles into merged reference
                        repo.AddListOfArticlesToBookmark(bookmarkInto, uniques);

                        // 3. Delete old reference
                        repo.DeleteBookmark(bookmarkFrom);
                    }
                }
                else
                {
                    new BugTracker().Track("Bookmark Editor", "Save Bookmark", e.Message, e.StackTrace);
                    _dialogService.OpenDialog(new DialogOkViewModel("Something went wrong.", "Error", DialogType.Error));
                }
            }
            finally
            {
                // 2. Refresh collections in parent;
                _parent.PopulateBookmarks();

                // 3. Close window
                (input as ICommand).Execute(null);
            }
        }
        public void Sync()
        {
            // 1. Sync information
            _logs.ForEach((log) =>
            {
                User user = new UserRepo().GetUserByName(log.Username);

                switch (log.Type)
                {
                case "Create":
                    // Create article
                    if (log.Info.InfoType == "ArticleInfo")
                    {
                        ArticleInfo local_info = log.Info as ArticleInfo;
                        Article article        = new Article(local_info);
                        ArticleRepo repo       = new ArticleRepo();

                        // Edge case: Article already exists
                        if (repo.GetArticleWithTitle(article.Title) != null)
                        {
                            string mismatch = $"Article '{local_info.Title}' already exists.";
                            _mismatches.Add(mismatch);
                            return;
                        }

                        // 1. Add article to database
                        repo.SaveArticle(article, user);

                        // 2. Copy file
                        string fileName = repo.GetFileWithTitle(local_info.Title);
                        File.Copy(
                            Path.Combine(_filesPath, local_info.FileName + ".pdf"),
                            Path.Combine(Path.Combine(Environment.CurrentDirectory, "Files"), fileName + ".pdf"));

                        Article dbArticle = repo.GetArticleWithTitle(local_info.Title);

                        // 3. Add references and bookmarks
                        BookmarkRepo bookmarkRepo   = new BookmarkRepo();
                        ReferenceRepo referenceRepo = new ReferenceRepo();

                        // Bookmarks
                        local_info.Bookmarks.ForEach((bookmark) =>
                        {
                            Bookmark dbBookmark = bookmarkRepo.GetBookmark(bookmark.Name, user);
                            bookmarkRepo.AddArticleToBookmark(dbBookmark, dbArticle);
                        });

                        // References
                        local_info.References.ForEach((reference) =>
                        {
                            Reference dbReference = referenceRepo.GetReference(reference.Name);
                            referenceRepo.AddArticleToReference(dbReference, dbArticle);
                        });
                    }
                    // Create bookmark
                    else if (log.Info.InfoType == "BookmarkInfo")
                    {
                        BookmarkInfo local_info = log.Info as BookmarkInfo;
                        BookmarkRepo repo       = new BookmarkRepo();

                        // Edge case: Bookmark already exists
                        if (repo.GetBookmark(local_info.Name, user) != null)
                        {
                            string mismatch = $"Bookmark '{local_info.Name}' already exists.";
                            _mismatches.Add(mismatch);
                            return;
                        }

                        repo.AddBookmark(local_info.Name, local_info.Global, user);
                    }
                    // Create reference
                    else if (log.Info.InfoType == "ReferenceInfo")
                    {
                        ReferenceInfo local_info = log.Info as ReferenceInfo;
                        ReferenceRepo repo       = new ReferenceRepo();

                        // Edge case: Reference already exists
                        if (repo.GetReference(local_info.Name) != null)
                        {
                            string mismatch = $"Reference '{local_info.Name}' already exists.";
                            _mismatches.Add(mismatch);
                            return;
                        }

                        new ReferenceRepo().AddReference(local_info.Name);
                    }
                    break;

                case "Update":
                    // Update article
                    if (log.Info.InfoType == "ArticleInfo")
                    {
                        ArticleInfo local_info  = (ArticleInfo)log.Info;
                        ArticleRepo repo        = new ArticleRepo();
                        Article existingArticle = repo.GetFullArticleWithTitle(user, log.Changed);

                        // Edge case: Article I am trying to update doesn't exist
                        if (existingArticle == null)
                        {
                            string mismatch = $"Article '{log.Changed}' doesn't exist and can't be updated.";
                            _mismatches.Add(mismatch);
                            return;
                        }

                        Article newArticle = new Article(local_info);
                        newArticle.ID      = existingArticle.ID;
                        repo.UpdateArticle(newArticle, user);
                    }
                    // Update bookmark
                    else if (log.Info.InfoType == "BookmarkInfo")
                    {
                        BookmarkInfo local_info   = (BookmarkInfo)log.Info;
                        BookmarkRepo repo         = new BookmarkRepo();
                        Bookmark existingBookmark = repo.GetBookmark(log.Changed, user);

                        // Edge case: Bookmark I am trying to update doesn't exist
                        if (existingBookmark == null)
                        {
                            string mismatch = $"Bookmark '{local_info.Name}' doesn't exist and can't be updated.";
                            _mismatches.Add(mismatch);
                            return;
                        }

                        Bookmark newBookmark = new Bookmark(local_info);
                        newBookmark.ID       = existingBookmark.ID;
                        repo.UpdateBookmark(newBookmark);
                    }
                    // Update reference
                    else if (log.Info.InfoType == "ReferenceInfo")
                    {
                        ReferenceInfo local_info    = (ReferenceInfo)log.Info;
                        ReferenceRepo repo          = new ReferenceRepo();
                        Reference existingReference = repo.GetReference(log.Changed);

                        // Edge case: Reference I am trying to update doesn't exist
                        if (existingReference == null)
                        {
                            string mismatch = $"Bookmark '{local_info.Name}' doesn't exist and can't be updated.";
                            _mismatches.Add(mismatch);
                            return;
                        }

                        Reference newReference = new Reference(local_info);
                        newReference.ID        = existingReference.ID;
                        if (local_info.Title != null)
                        {
                            newReference.ArticleID = (int)new ArticleRepo().GetArticleWithTitle(local_info.Title).ID;
                        }
                        repo.UpdateReference(newReference);
                    }
                    break;

                case "Coupling":
                    Couple info = (Couple)log.Info;
                    // Couple bookmark
                    if (info.CollectionType == "Bookmark")
                    {
                        BookmarkRepo bookmarkRepo = new BookmarkRepo();
                        ArticleRepo articleRepo   = new ArticleRepo();

                        Bookmark bookmark = bookmarkRepo.GetBookmark(info.Name, user);
                        Article article   = articleRepo.GetArticleWithTitle(info.Title);

                        // Edge case: Article or bookmark doesn't exist or Article is already in bookmark
                        if (bookmark == null)
                        {
                            string mismatch = $"Can't couple article - '{info.Title}' with bookmark '{info.Name}' because bookmark doesn't exist";
                            _mismatches.Add(mismatch);
                            return;
                        }
                        else if (article == null)
                        {
                            string mismatch = $"Can't couple article - '{info.Title}' with bookmark '{info.Name}' because article doesn't exist";
                            _mismatches.Add(mismatch);
                            return;
                        }

                        // Add
                        if (info.ActionType == "Add")
                        {
                            // Edge case: Article is already in bookmark
                            if (bookmarkRepo.CheckArticleInBookmark(bookmark, article))
                            {
                                string mismatch = $"Article - '{info.Title}' is already in bookmark '{info.Name}'";
                                _mismatches.Add(mismatch);
                                return;
                            }
                            bookmarkRepo.AddArticleToBookmark(bookmark, article);
                        }
                        // Remove
                        else if (info.ActionType == "Remove")
                        {
                            // Edge case: Article is not in bookmark
                            if (!bookmarkRepo.CheckArticleInBookmark(bookmark, article))
                            {
                                string mismatch = $"Article - '{info.Title}' can not be removed from bookmark '{info.Name}' (Its not there)";
                                _mismatches.Add(mismatch);
                                return;
                            }
                            bookmarkRepo.RemoveArticleFromBookmark(bookmark, article);
                        }
                    }
                    // Couple reference
                    else if (info.CollectionType == "Reference")
                    {
                        ReferenceRepo referenceRepo = new ReferenceRepo();
                        ArticleRepo articleRepo     = new ArticleRepo();

                        Reference reference = referenceRepo.GetReference(info.Name);
                        Article article     = articleRepo.GetArticleWithTitle(info.Title);

                        // Edge case: Article or bookmark doesn't exist
                        if (reference == null)
                        {
                            string mismatch = $"Can't couple article - '{info.Title}' with reference '{info.Name}' because reference doesn't exist";
                            _mismatches.Add(mismatch);
                            return;
                        }
                        else if (article == null)
                        {
                            string mismatch = $"Can't couple article - '{info.Title}' with reference '{info.Name}' because article doesn't exist";
                            _mismatches.Add(mismatch);
                            return;
                        }

                        // Add
                        if (info.ActionType == "Add")
                        {
                            if (referenceRepo.CheckArticleInReference(reference, article))
                            {
                                string mismatch = $"Article - '{info.Title}' is already in reference '{info.Name}'";
                                _mismatches.Add(mismatch);
                                return;
                            }
                            referenceRepo.AddArticleToReference(reference, article);
                        }
                        // Remove
                        else if (info.ActionType == "Remove")
                        {
                            if (!referenceRepo.CheckArticleInReference(reference, article))
                            {
                                string mismatch = $"Article - '{info.Title}' is already in bookmark '{info.Name}'";
                                _mismatches.Add(mismatch);
                                return;
                            }
                            referenceRepo.RemoveArticleFromReference(reference, article);
                        }
                    }
                    break;

                case "Delete":
                    DeleteInfo local_info1 = (DeleteInfo)log.Info;
                    // Delete article
                    if (local_info1.ObjectType == "Article")
                    {
                        ArticleRepo repo = new ArticleRepo();
                        Article article  = repo.GetArticleWithTitle(local_info1.Name);

                        // Edge case: Article I am trying to delete doesn't exist
                        if (article == null)
                        {
                            string mismatch = $"Can't delete article '{local_info1.Name}' because it doesn't exist";
                            _mismatches.Add(mismatch);
                            return;
                        }

                        string file = repo.GetFileWithTitle(local_info1.Name);
                        repo.DeleteArticle(article);
                        File.Delete(Path.Combine(Environment.CurrentDirectory, "Files", file + ".pdf"));
                    }
                    // Delete bookmark
                    else if (local_info1.ObjectType == "Bookmark")
                    {
                        BookmarkRepo repo = new BookmarkRepo();
                        Bookmark bookmark = repo.GetBookmark(local_info1.Name, user);

                        // Edge case: Bookmark I am trying to delete doesn't exist
                        if (bookmark == null)
                        {
                            string mismatch = $"Can't delete bookmark '{local_info1.Name}' because it doesn't exist";
                            _mismatches.Add(mismatch);
                            return;
                        }

                        repo.DeleteBookmark(bookmark);
                    }
                    // Delete reference
                    else if (local_info1.ObjectType == "Reference")
                    {
                        ReferenceRepo repo  = new ReferenceRepo();
                        Reference reference = repo.GetReference(local_info1.Name);

                        // Edge case: Reference I am trying to delete doesn't exist
                        if (reference == null)
                        {
                            string mismatch = $"Can't delete reference '{local_info1.Name}' because it doesn't exist";
                            _mismatches.Add(mismatch);
                            return;
                        }

                        repo.DeleteReference(reference);
                    }
                    break;

                case "Personal":
                    PersonalInfo local_info2 = (PersonalInfo)log.Info;
                    ArticleRepo repo1        = new ArticleRepo();
                    Article article3         = repo1.GetArticleWithTitle(local_info2.Title);

                    // Edge case: Article I am trying to add personal doesn't exist
                    if (article3 == null)
                    {
                        string mismatch = $"Can't add personal to article '{local_info2.Title}' because it doesn't exist";
                        _mismatches.Add(mismatch);
                        return;
                    }

                    article3.PersonalComment = local_info2.PersonalComment;
                    article3.SIC             = local_info2.SIC;

                    repo1.UpdatePersonal(article3, user);
                    break;

                case "Pending":
                    PendingInfo l_info = (PendingInfo)log.Info;

                    // 1. Remove pending section status from db
                    new GlobalRepo().RemovePending(l_info.Section);

                    // 2. Remove section from json
                    string path            = Path.Combine(Environment.CurrentDirectory, "sections.json");
                    string textInfo        = File.ReadAllText(path);
                    List <string> sections = JsonConvert.DeserializeObject <List <string> >(textInfo);
                    sections.Remove(l_info.Section);
                    textInfo = JsonConvert.SerializeObject(sections);
                    File.WriteAllText(path, textInfo);
                    break;

                default:
                    break;
                }
            });

            // 2. Write mismatches
            WriteMismatches();
        }