/// <summary> /// Ensures this container has the same state as the one given, using the least amount of operations /// </summary> /// <param name="otherContainer">The container to match</param> public void Reconcile(Container otherContainer) { Size = otherContainer.Size; if (Empty) { items.AddRange(otherContainer.items); OnContainerChanged(otherContainer.Items, ContainerChangeType.Add); return; } if (otherContainer.Empty) { Dump(); return; } // Loop through all items to find the first index of divergence // We can assume that all items after that point have been changed, as items are always inserted at the end List <Item> movedItems = new List <Item>(); int changedIndex = -1; for (var i = 0; i < items.Count; i++) { StoredItem storedItem = items[i]; StoredItem otherContainerItem = otherContainer.items[i]; if (storedItem.Item != otherContainerItem.Item) { changedIndex = i; break; } if (storedItem.Position != otherContainerItem.Position) { movedItems.Add(storedItem.Item); } } // Invoke move logic if any element has moved if (movedItems.Count > 0) { OnContainerChanged(movedItems, ContainerChangeType.Move); } // Nothing actually changed if (changedIndex == -1) { return; } // Remove all items after first divergence Item[] removedItems = new Item[items.Count - changedIndex]; for (var i = changedIndex; i < items.Count;) { items.RemoveAt(i); } OnContainerChanged(removedItems.AsEnumerable(), ContainerChangeType.Remove); // Add all remaining items for (int i = changedIndex; i < otherContainer.ItemCount; i++) { items.Add(otherContainer.items[i]); } OnContainerChanged(otherContainer.Items.Skip(changedIndex + 1), ContainerChangeType.Add); }