                 items[index] = newValue
             }
         }
+
+        public var debugDescription: String {
+            return "\(value): \(items.debugDescription)"
+        }
+    }
+
+    public enum Element {
+        case section(Section)
+        case item(Item)
+
+        public var section: Section? {
+            if case .section(let section) = self {
+                return section
+            } else {
+                return nil
+            }
+        }
+
+        public var item: Item? {
+            if case .item(let item) = self {
+                return item
+            } else {
+                return nil
+            }
+        }
     }
 
     public var sections: [Section]


import Foundation

public protocol Array2DProtocol: RangeReplaceableCollection {
    associatedtype Value
    associatedtype Item
    var array2DView: Array2D<Value, Item> { get set }
}

public struct Array2D<Value, Item>: Array2DProtocol {

    public struct Section: MutableCollection {

        public var value: Value
        public var items: [Item]

    }

    public var startIndex: IndexPath {
        return IndexPath(index: 0)
    }

    public var endIndex: IndexPath {
        return IndexPath(index: sections.count)
    }

    public func index(after i: IndexPath) -> IndexPath {
        if i.count == 1 {
            if i[0] < sections.count {
                let section = sections[i[0]]
                if section.count > 0 {
                    return IndexPath(item: 0, section: i[0])
                }  else {
                    return IndexPath(index: i[0] + 1)
                }
            } else {
                return endIndex
            }
        } else if i.count == 2 {
            if i.item < sections[i.section].count - 1 {
                return IndexPath(item: i.item + 1, section: i.section)
            } else {
                return IndexPath(index: i.section + 1)
            }
        } else {
            fatalError()
        }
    }

    public var isEmpty: Bool {
        return count == 0
    }

    public var count: Int {
        return sections.reduce(0) { $0 + $1.items.count + 1 }
    }

    public subscript(indexPath: IndexPath) -> Element {
        get {
            if indexPath.count == 1 {
                return .section(sections[indexPath[0]])
            } else if indexPath.count == 2 {
                return .item(sections[indexPath.section].items[indexPath.item])
            } else {
                fatalError()
            }
        }
        set {
            switch (indexPath.count, newValue) {
            case (1, .section(let section)):
                sections[indexPath.section] = section
            case (2, .item(let item)):
                sections[indexPath.section].items[indexPath.item] = item
            default:
                fatalError()
            }
        }
    }

    public mutating func replaceSubrange<C>(_ subrange: Range<IndexPath>, with newElements: C) where C: Collection, Array2D<Value, Item>.Element == C.Element {
        let lower = subrange.lowerBound
        let upper = subrange.upperBound
        if lower.count == 1 && index(after: lower) == upper && newElements.count == 0 {
            sections.remove(at: lower[0])
            return
        }
        guard upper.count == lower.count else {
            fatalError("Unsupproted range \(subrange). Plase replace only sections or only items within as single section.")
        }
        if lower.count == 1 {
            sections.replaceSubrange(lower[0]..<upper[0], with: newElements.map { $0.section! })
        } else if lower.count == 2 {
            sections[lower.section].items.replaceSubrange(lower.item..<upper.item, with: newElements.map { $0.item! })
        } else {
            fatalError("Unsupported index.")
        }
    }

