 }
 
 extension TableViewManager {
-
+    
     fileprivate func item(forIndexPath indexPath: IndexPath) -> Item {
         return sections[indexPath.section].items[indexPath.row]
     }

            return value
        }
    }

    fileprivate func height(forKey key: (Section) -> HeaderFooterView, inSection section: Int) -> CGFloat? {
        guard case .view(let view) = key(sections[section]), let value = view.height
            else { return nil }
        return height(value)
    }

    fileprivate func height(atIndexPath indexPath: IndexPath) -> CGFloat? {
        guard let value = item(forIndexPath: indexPath).height else { return nil }
        return height(value)
    }

    fileprivate func height(_ height: ImmutableMutableHeight) -> CGFloat {
        switch height {
        case .immutable(let value):

            return UITableViewAutomaticDimension
        }
    }
    
}

extension TableViewManager: UITableViewDataSource {
    
    public func numberOfSections(in tableView: UITableView) -> Int {
        return sections.count
    }
    
    public func tableView(_ tableView: UITableView, numberOfRowsInSection sectionIndex: Int) -> Int {
        let section = sections[sectionIndex]
        return section.items.count
    }
    
    public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let currentItem = item(forIndexPath: indexPath)
        let drawer = currentItem.drawer
        
        let cell = drawer.cell(inManager: self, withItem: currentItem, forIndexPath: indexPath)
        drawer.draw(cell, withItem: currentItem)
        
        return cell
    }
    
    
    public func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return title(forKey: {$0.header}, inSection: section)
    }
    
    
    public func tableView(tableView: UITableView, titleForFooterInSection section: Int) -> String? {
        return title(forKey: {$0.footer}, inSection: section)
    }
    
    
}

extension TableViewManager: UITableViewDelegate {
    
    public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        guard let currentItem = item(forIndexPath: indexPath) as? Selectable else { return }
        currentItem.onSelection(currentItem)
    }
    
    public func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: IndexPath) -> CGFloat {
        return height(atIndexPath: indexPath) ?? tableView.rowHeight
    }
    
    public func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return height(forKey: {$0.header}, inSection: section) ?? tableView.sectionHeaderHeight
    }
    
    public func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
        return height(forKey: {$0.footer}, inSection: section) ?? tableView.sectionFooterHeight
    }
    
    public func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: IndexPath) -> CGFloat {
        return estimatedHeight(atIndexPath: indexPath) ?? tableView.estimatedRowHeight
    }
    
    public func tableView(tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat {
        return estimatedHeight(forKey: {$0.header}, inSection: section) ?? tableView.estimatedSectionHeaderHeight
    }
    
    public func tableView(tableView: UITableView, estimatedHeightForFooterInSection section: Int) -> CGFloat {
        return estimatedHeight(forKey: {$0.footer}, inSection: section) ?? tableView.estimatedSectionHeaderHeight
    }
    
    public func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        return view(forKey: {$0.header}, inSection: section)
    }
    
    public func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
        return view(forKey: {$0.footer}, inSection: section)
    }
    
}
