     }
   }
 
-
-  // External Interface
-  func appendItem(item: T) {
-    dispatch_async(dataMutationDispatchQueue) {
-      if self.items.count == 0 {
-        self.items.append([])
-      }
-      self.pendingChanges.append(DataChange.Insert(item, NSIndexPath(forItem: self.items[0].count, inSection: 0))) // This must happen before items array is mutated
-      self.items[0].append(item)
-      if let lastOperation = self.mutateDisplayQueue.operations.last {
-        if lastOperation.executing {
-          let applyChangeOp = ApplyDataSourceChangeOperation(safeDataSource: self, collectionView: self.collectionView)
-          self.mutateDisplayQueue.addOperation(applyChangeOp)
-        }
-      } else {
+  func addApplyOperationIfNeeded() {
+    if let lastOperation = self.mutateDisplayQueue.operations.last {
+      if lastOperation.executing {
         let applyChangeOp = ApplyDataSourceChangeOperation(safeDataSource: self, collectionView: self.collectionView)
         self.mutateDisplayQueue.addOperation(applyChangeOp)
       }
-    }
-  }
-
-  // Instead allow consumer to give you a closure that we call and provide current 
+    } else {
+      let applyChangeOp = ApplyDataSourceChangeOperation(safeDataSource: self, collectionView: self.collectionView)
+      self.mutateDisplayQueue.addOperation(applyChangeOp)
+    }
+  }
+
+
+  // External Interface
+  public func appendItem(item: T) {
+    dispatch_async(dataMutationDispatchQueue) {
+      // Automatically creates section 0 if it does not exist already.
+      if self.items.count == 0 {
+        self.unsafeAppendSectionWithItem(item)
+      } else {
+//        self.unsafeAppendItem(item, toSection: 0) // TODO: Remove ObjC msg_send overhead
+
+        let section = 0
+        guard section < self.items.count else { return } // TODO: Add more of these validations
+        let startingIndex = self.items[section].count
+        self.pendingChanges.append(.InsertItem(item, NSIndexPath(forItem: startingIndex, inSection: section)))
+        self.items[section].append(item)
+        self.addApplyOperationIfNeeded()
+      }
+    }
+  }
+
+  public func appendItem(item: T, toSection section: Int) {
+    dispatch_async(dataMutationDispatchQueue) {
+      self.unsafeAppendItem(item, toSection: section)
+    }
+  }
+
+  @nonobjc @inline(__always)
+  func unsafeAppendItem(item: T, toSection section: Int) {
+    guard section < self.items.count else { return } // TODO: Add more of these validations
+    let startingIndex = self.items[section].count
+    self.pendingChanges.append(.InsertItem(item, NSIndexPath(forItem: startingIndex, inSection: section)))
+    self.items[section].append(item)
+    self.addApplyOperationIfNeeded()
+  }
+
+  public func appendSectionWithItems(items: [T]) {
+    dispatch_async(dataMutationDispatchQueue) {
+      self.unsafeAppendSectionWithItems(items)
+    }
+  }
+
+  @nonobjc @inline(__always)
+  func unsafeAppendSectionWithItems(items: [T]) {
+    let newSectionIndex = self.items.count // This must happen first.
+    self.pendingChanges.append(.AppendSection)
+    self.items.append([])
+    let indexPaths = items.enumerate().map { (index, item) -> NSIndexPath in
+      return NSIndexPath(forItem: index, inSection: newSectionIndex)
+    }
+    self.pendingChanges.append(.InsertItems(items, indexPaths))
+    self.items[newSectionIndex] = items
+    self.addApplyOperationIfNeeded()
+  }
+
+  @nonobjc @inline(__always)
+  func unsafeAppendSectionWithItem(item: T) {
+    let newSectionIndex = self.items.count // This must happen first.
+    self.pendingChanges.append(.AppendSection)
+    self.items.append([])
+    let indexPath = NSIndexPath(forItem: 0, inSection: newSectionIndex)
+    self.pendingChanges.append(.InsertItem(item, indexPath))
+    self.items[newSectionIndex].append(item)
+    self.addApplyOperationIfNeeded()
+  }
+
+  // Instead allow consumer to give you a closure that we call and provide current
   //   data state and they can use that state to apply mutations
-  func insertItem(item: T, atIndex: Int) {
+  public func insertItemWithClosure(getInsertionIndexPath: ([[T]]) -> (item: T, indexPath: NSIndexPath)?) {
     dispatch_async(dataMutationDispatchQueue) {
-
-    }
-  }
-
-  func removeItemAtIndex(index: Int) {
+      guard let insertion = getInsertionIndexPath(self.items) else { return }
+      insertion.indexPath.item
+      self.pendingChanges.append(.InsertItem(insertion.item, insertion.indexPath))
+      self.items[insertion.indexPath.section].insert(insertion.item, atIndex: insertion.indexPath.item)
+      self.addApplyOperationIfNeeded()
+    }
+  }
+
+  public func deleteItemWithClosure(getDeletionIndexPath: ([[T]]) -> NSIndexPath?) {
     dispatch_async(dataMutationDispatchQueue) {
-
-    }
-  }
-
-
-
-  func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
+      self.items[0].count
+      guard let indexPath = getDeletionIndexPath(self.items) else { return }
+      self.pendingChanges.append(.DeleteItem(indexPath))
+      self.items[indexPath.section].removeAtIndex(indexPath.item)
+      self.addApplyOperationIfNeeded()
+      self.items[0].count
+    }
+  }
+
+  public func deleteLastItemInSection(sectionIndex: Int) {
+    dispatch_async(dataMutationDispatchQueue) {
+      if self.items[sectionIndex].count > 0 {
+        self.items[sectionIndex].removeLast()
+        self.pendingChanges.append(.DeleteLastItem(sectionIndex))
+        self.addApplyOperationIfNeeded()
+      }
+    }
+  }
+
+
+
+  public func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
     return dataSourceItems[section].count
   }
 
-  func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
-    return cellProvider.collectionView(collectionView, cellForItem: items[indexPath.section][indexPath.row], atIndexPath: indexPath)
-  }
-
-  func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
+  public func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
+    let cell = cellForItemAtIndexPath(collectionView, dataSourceItems[indexPath.section][indexPath.row], indexPath)
+    return cell
+  }
+
+  public func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
     return dataSourceItems.count
   }
 


}

let cellProvider = ColorCellProvider()

let flowLayout = UICollectionViewFlowLayout()
flowLayout.itemSize = CGSizeMake(10, 10)
let collectionView = UICollectionView(frame: CGRectZero, collectionViewLayout: flowLayout)
let safeDataSource = SafeDataSource<Color>(collectionView: collectionView, cellProvider: cellProvider)
collectionView.dataSource = safeDataSource
collectionView.frame = CGRectMake(0, 0, 500, 1000)
collectionView.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: "cell")


collectionView.addGestureRecognizer(tgr)

dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)) {
  for _ in (0...19) {
    interactionHandler.handleTap()
  }

  interactionHandler.safeDataSource.insertItemWithClosure { colors in
    print("Insert item")
    if colors.count > 0 {
      if colors[0].count > 10 {
        colors[0].count - 8
        let indexPath = NSIndexPath(forItem: 4, inSection: 0)
        indexPath.item
        return (Color(hue: 0.1, saturation: 1.0, brightness: 0.9), indexPath)
      }
    }
    return nil
  }

  for _ in (0...1) { // TODO: Try (0...1) and this will crash, support multiple consecutive deletes
    interactionHandler.safeDataSource.deleteItemWithClosure { colors in
      print("Delete item: loop")
      if colors.count > 0 {
        if colors[0].count > 10 {
          return NSIndexPath(forItem: colors[0].count - 2, inSection: 0)
        }
      }
      return nil
    }
  }

  interactionHandler.safeDataSource.deleteItemWithClosure { colors in
    print("Delete item: last")
    return NSIndexPath(forItem: 0, inSection: 0)
  }

  interactionHandler.safeDataSource.deleteLastItemInSection(0)
  interactionHandler.safeDataSource.deleteLastItemInSection(0)
  interactionHandler.safeDataSource.deleteLastItemInSection(0)
  interactionHandler.safeDataSource.deleteLastItemInSection(0)
  interactionHandler.safeDataSource.deleteLastItemInSection(0)
  interactionHandler.safeDataSource.deleteLastItemInSection(0)
  interactionHandler.safeDataSource.deleteLastItemInSection(0)
  interactionHandler.safeDataSource.deleteLastItemInSection(0)
  interactionHandler.safeDataSource.deleteLastItemInSection(0)
  interactionHandler.safeDataSource.deleteLastItemInSection(0)
  interactionHandler.safeDataSource.deleteLastItemInSection(0)
  interactionHandler.safeDataSource.deleteLastItemInSection(0)
  interactionHandler.safeDataSource.deleteLastItemInSection(0)
  interactionHandler.safeDataSource.deleteLastItemInSection(0)
//  interactionHandler.safeDataSource.deleteLastItemInSection(0) // TODO: uncomment and support this use case

}











