private static bool SyncPrivate(FlowObservableCollection <T> currentItems, FlowObservableCollection <T> updateItems, bool notify)
        {
            currentItems?.OnCollectionChangedSuspend();

            var itemsAdded   = notify ? new List <T>() : null;
            var itemsRemoved = notify ? new List <T>() : null;
            //var itemsMoved = notify ? new List<T>() : null;
            //var itemsMovedIndexes = notify ? new List<Tuple<int, int>>() : null;

            bool structureIsChanged = false;
            bool forceReset         = false;

            var isGroup = updateItems.First() is FlowGroup;

            if (isGroup)
            {
                var result = updateItems
                             .Join(currentItems, k => ((FlowGroup)(object)k).Key, i => ((FlowGroup)(object)i).Key, (k, i) => i)
                             .ToList();

                for (int i = 0; i < result.Count; i++)
                {
                    var oldGroup = currentItems[i] as FlowGroup;
                    var newGroup = result[i] as FlowGroup;

                    if (oldGroup.Key != newGroup.Key)
                    {
                        forceReset      = true;
                        currentItems[i] = (T)(object)newGroup;
                    }
                }
            }

            for (int i = 0; i < updateItems.Count; i++)
            {
                var item = updateItems[i];

                if (currentItems.Count <= i)
                {
                    structureIsChanged = true;
                    currentItems.Add(item);
                    itemsAdded?.Add(item);
                }
                else
                {
                    var itemList        = item as FlowObservableCollection <object>;
                    var currentItem     = currentItems[i];
                    var currentItemList = currentItem as FlowObservableCollection <object>;

                    if (itemList != null && currentItemList != null)
                    {
                        if (currentItemList.Sync(itemList, false))
                        {
                            structureIsChanged = true;
                        }
                    }
                    else if (structureIsChanged)
                    {
                        currentItems[i] = item;
                    }
                    else if ((object)item != (object)currentItem)
                    {
                        structureIsChanged = true;
                        currentItems[i]    = item;
                    }
                }
            }

            while (currentItems.Count > updateItems.Count)
            {
                structureIsChanged = true;
                itemsRemoved?.Add(currentItems[currentItems.Count - 1]);
                currentItems.RemoveAt(currentItems.Count - 1);
            }

            if (forceReset || structureIsChanged)
            {
                if (!forceReset && itemsAdded != null && itemsRemoved == null && itemsAdded.Count < 100)
                {
                    currentItems?.OnCollectionChangedCancel();
                    currentItems?.NotifyCollectionChanged(
                        new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, itemsAdded));
                }
                else if (!forceReset && itemsRemoved != null && itemsAdded == null && itemsRemoved.Count < 100)
                {
                    currentItems?.NotifyCollectionChanged(
                        new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, itemsRemoved));
                }
                else
                {
                    currentItems?.OnCollectionChangedResume();
                }
            }
            else
            {
                currentItems?.OnCollectionChangedCancel();
            }

            return(structureIsChanged);
        }
 internal bool Sync(FlowObservableCollection <T> newItems, bool notify = true)
 {
     return(SyncPrivate(this, newItems, notify));
 }