 import Differ
 import ReactiveKit
 
-public enum ObservableCollectionChange<UnderlyingCollection: Collection>: Equatable {
+public enum ObservableCollectionChange<Index: Equatable>: Equatable {
     case reset
-    case inserts([UnderlyingCollection.Index])
-    case deletes([UnderlyingCollection.Index])
-    case updates([UnderlyingCollection.Index])
-    case move(UnderlyingCollection.Index, UnderlyingCollection.Index)
+    case inserts([Index])
+    case deletes([Index])
+    case updates([Index])
+    case move(Index, Index)
     case beginBatchEditing
     case endBatchEditing
 }
 
 public protocol ObservableCollectionEventProtocol {
-    associatedtype UnderlyingCollection: Collection & DataSourceProtocol
-
-    var change: ObservableCollectionChange<UnderlyingCollection> { get }
+    associatedtype UnderlyingCollection: Collection
+
+    var change: ObservableCollectionChange<UnderlyingCollection.Index> { get }
     var source: UnderlyingCollection { get }
 }
 
-public struct ObservableCollectionEvent<UnderlyingCollection: Collection & DataSourceProtocol>: ObservableCollectionEventProtocol {
-    public let change: ObservableCollectionChange<UnderlyingCollection>
+public struct ObservableCollectionEvent<UnderlyingCollection: Collection>: ObservableCollectionEventProtocol {
+    public let change: ObservableCollectionChange<UnderlyingCollection.Index>
     public let source: UnderlyingCollection
 
-    public init(change: ObservableCollectionChange<UnderlyingCollection>, source: UnderlyingCollection) {
+    public init(change: ObservableCollectionChange<UnderlyingCollection.Index>, source: UnderlyingCollection) {
         self.change = change
         self.source = source
     }
 }
 
-public struct ObservableCollectionPatchEvent<UnderlyingCollection: Collection & DataSourceProtocol>: ObservableCollectionEventProtocol {
-    public let change: ObservableCollectionChange<UnderlyingCollection>
+public struct ObservableCollectionPatchEvent<UnderlyingCollection: Collection>: ObservableCollectionEventProtocol {
+    public let change: ObservableCollectionChange<UnderlyingCollection.Index>
     public let source: UnderlyingCollection
 
-    public init(change: ObservableCollectionChange<UnderlyingCollection>, source: UnderlyingCollection) {
+    public init(change: ObservableCollectionChange<UnderlyingCollection.Index>, source: UnderlyingCollection) {
         self.change = change
         self.source = source
     }
 }
 
-public class ObservableCollection<UnderlyingCollection: Collection & DataSourceProtocol>: SignalProtocol {
+public class ObservableCollection<UnderlyingCollection: Collection>: SignalProtocol {
     public fileprivate(set) var collection: UnderlyingCollection
     public let subject = PublishSubject<ObservableCollectionEvent<UnderlyingCollection>, NoError>()
     public let lock = NSRecursiveLock(name: "com.reactivekit.bond.observable-collection")


        // use proxy to collect changes
        let proxy = MutableObservableCollection(collection)
        var patch: [ObservableCollectionChange<UnderlyingCollection>] = []
        let disposable = proxy.skip(first: 1).observeNext { event in
            patch.append(event.change)
        }

}

// swiftlint:disable:next function_body_length
func generateDiff<Index, C: Collection>(from sequenceOfChanges: [ObservableCollectionChange<Index>], in list: C) -> [ObservableCollectionChange<Index>] where C.Index == Index {
    var diff = sequenceOfChanges.flatMap { $0.unwrap(using: list) }

    for i in 0..<diff.count {
