private void AfterUpdate(BaseItem sourceItem, BaseItem targetItem)
        {
            if (targetItem.Association == null)
            {
                targetItem.Association = sourceItem.Association;
            }
            targetItem.ChangeNumber = sourceItem.ChangeNumber;
            var link = LinkStatusTableModel.GetDefault().GetItem(sourceItem);

            if (link != null)
            {
                link.ChangeNumber = sourceItem.ChangeNumber;
                LinkStatusTableModel.GetDefault().UpdateItem(link, link.Id);
                targetItem.Id = link.TargetItemId;
                ItemTableModel.GetDefault().UpdateItem(sourceItem, sourceItem.Id);
                ItemTableModel.GetDefault().UpdateItem(targetItem, targetItem.Id);
            }
            var historyEntry = new SyncHistoryEntry();

            historyEntry.CreateDate   = DateTime.Now;
            historyEntry.SourceItemId = sourceItem.Id;
            historyEntry.TargetItemId = targetItem.Id;
            historyEntry.Result       = sourceItem.AdapterType == _sourceEntityAdapter.GetType()
                ? SyncResult.Sent
                : SyncResult.Received;
            SyncHistoryTableModel.GetDefault().InsertItem(historyEntry);
        }
        private void AfterInsert(BaseItem sourceItem, BaseItem targetItem)
        {
            if (targetItem.Association == null)
            {
                targetItem.Association = sourceItem.Association;
            }
            //check if item with same path already exists
            var existingItem = ItemTableModel.GetDefault().GetItem(targetItem);

            if (existingItem != null)
            {
                ItemTableModel.GetDefault().UpdateItem(targetItem, existingItem.Id);
                targetItem.Id = existingItem.Id;
            }
            else
            {
                ItemTableModel.GetDefault().InsertItem(targetItem);
                targetItem = ItemTableModel.GetDefault().GetLastInsertItem();
            }

            if (LinkStatusTableModel.GetDefault().GetItem(sourceItem) == null)
            {
                var link = new LinkStatus(sourceItem, targetItem);
                LinkStatusTableModel.GetDefault().InsertItem(link);
            }

            var historyEntry = new SyncHistoryEntry();

            historyEntry.CreateDate   = DateTime.Now;
            historyEntry.SourceItemId = sourceItem.Id;
            historyEntry.TargetItemId = targetItem.Id;
            historyEntry.Result       = sourceItem.AdapterType == _sourceEntityAdapter.GetType()
                ? SyncResult.Sent
                : SyncResult.Received;
            SyncHistoryTableModel.GetDefault().InsertItem(historyEntry);
        }
        protected async Task ProcessDeletions(List <BaseItem> deletedItems)
        {
            await SetExecutionStatus(ExecutionStatus.Deletions);

            foreach (var item in deletedItems)
            {
                try
                {
                    if (item.AdapterType == _targetEntityAdapter.GetType() &&
                        item.Association.SyncDirection == SyncDirection.FullSync)
                    {
                        await _sourceEntityAdapter.DeleteItem(item);
                    }

                    if (item.AdapterType == _sourceEntityAdapter.GetType() &&
                        item.Association.SyncDirection == SyncDirection.FullSync)
                    {
                        await _targetEntityAdapter.DeleteItem(item);
                    }

                    var link = LinkStatusTableModel.GetDefault().GetItem(item);
                    if (link != null && item.Association.SyncDirection == SyncDirection.FullSync)
                    {
                        //the linked item should only be deleted from the database if its a full sync
                        //otherwise changes might not be tracked anymore if the user makes changes to the sync direction
                        var linkedItem = ItemTableModel.GetDefault().GetItem(link.TargetItemId);
                        if (linkedItem != null)
                        {
                            if (linkedItem.IsCollection)
                            {
                                var childItems = ItemTableModel.GetDefault().GetFilesForFolder(linkedItem.EntityId);
                                foreach (var childItem in childItems)
                                {
                                    var childLink = LinkStatusTableModel.GetDefault().GetItem(childItem);
                                    if (childLink != null)
                                    {
                                        LinkStatusTableModel.GetDefault().DeleteItem(childLink.Id);
                                    }
                                    ItemTableModel.GetDefault().DeleteItem(childItem.Id);
                                }
                            }
                            ItemTableModel.GetDefault().DeleteItem(linkedItem.Id);
                            var historyEntry = new SyncHistoryEntry();
                            historyEntry.CreateDate         = DateTime.Now;
                            historyEntry.Result             = SyncResult.Deleted;
                            historyEntry.OldItemDisplayName = item.DisplayName;
                            SyncHistoryTableModel.GetDefault().InsertItem(historyEntry);
                        }
                    }

                    if (link != null)
                    {
                        LinkStatusTableModel.GetDefault().DeleteItem(link.Id);
                    }

                    if (item.IsCollection)
                    {
                        var childItems = ItemTableModel.GetDefault().GetFilesForFolder(item.EntityId);
                        foreach (var childItem in childItems)
                        {
                            ItemTableModel.GetDefault().DeleteItem(childItem.Id);
                            _deletedCount++;
                        }
                    }
                    ItemTableModel.GetDefault().DeleteItem(item.Id);
                    _deletedCount++;
                }
                catch (Exception e)
                {
                    ToastHelper.SendToast(string.Format("Message: {0}, EntitityId: {1}", e.Message, item.EntityId));
                    await
                    LogHelper.Write(string.Format("Message: {0}, EntitityId: {1} StackTrace:\r\n{2}", e.Message,
                                                  item.EntityId, e.StackTrace));
                }
            }
        }
        protected async Task ProcessUpdates(IEnumerable <dynamic> itemsToUpdate)
        {
            var toUpdate = itemsToUpdate as IList <dynamic> ?? itemsToUpdate.ToList();
            await LogHelper.Write($"{toUpdate.Count} items to update");

            foreach (var item in toUpdate)
            {
                try
                {
                    await SetExectuingFileName(item.BaseItem.EntityId);

                    if (ExecutionContext.Instance.Status == ExecutionStatus.Stopped)
                    {
                        break;
                    }

                    //the root item of an association should not be created again
                    if (item.BaseItem.Id == item.BaseItem.Association.LocalFolderId || item.BaseItem.Id == item.BaseItem.Association.RemoteFolderId)
                    {
                        continue;
                    }
                    //skip files bigger than 50MB, these will have to be synced manually
                    //otherwise the upload/download could take too long and task would be terminated
                    //TODO make this configurable
                    if (item.BaseItem.Size > (50 * 1024 * 1024) & _isBackgroundTask)
                    {
                        item.BaseItem.SyncPostponed = true;
                        ItemTableModel.GetDefault().UpdateItem(item.BaseItem, item.BaseItem.Id);
                        continue;
                    }

                    //get the linked item
                    var linkedItem =
                        ItemTableModel.GetDefault()
                        .GetItem(item.BaseItem.Id == item.LinkStatus.SourceItemId
                                ? item.LinkStatus.TargetItemId
                                : item.LinkStatus.SourceItemId);
                    //if both (item and the linkedItem) have a higher changenum than the link we have a conflict.
                    //That means both item have been updated since the last time we checked.
                    //so we check which one has the latest change and if it is the current item we update ititem.LinkStatus
                    if (linkedItem != null && item.BaseItem.ChangeNumber > item.LinkStatus.ChangeNumber &&
                        linkedItem.ChangeNumber > item.LinkStatus.ChangeNumber)
                    {
                        if (item.BaseItem.LastModified > linkedItem.LastModified)
                        {
                            var result = await Update(item.BaseItem);

                            AfterUpdate(item.BaseItem, result);
                        }
                    }
                    else
                    {
                        var result = await Update(item.BaseItem);

                        AfterUpdate(item.BaseItem, result);
                    }
                    if (await TimeIsOver())
                    {
                        break;
                    }
                }
                catch (Exception e)
                {
                    var historyEntry = new SyncHistoryEntry();
                    historyEntry.CreateDate   = DateTime.Now;
                    historyEntry.SourceItemId = item.BaseItem.Id;
                    historyEntry.Result       = SyncResult.Failed;
                    historyEntry.Message      = e.Message;
                    SyncHistoryTableModel.GetDefault().InsertItem(historyEntry);
                    ToastHelper.SendToast(string.Format("Message: {0}, EntitityId: {1}", e.Message, item.BaseItem.EntityId));
                    await
                    LogHelper.Write(string.Format("Message: {0}, EntitityId: {1} StackTrace:\r\n{2}", e.Message,
                                                  item.BaseItem.EntityId, e.StackTrace));
                }
            }
        }