//
//  AutocompleteViewController.swift
//  App
//
//  Created by James Magahern on 9/21/20.
//

import UIKit

protocol AutocompleteViewControllerDelegate: AnyObject {
    func autocompleteController(_: AutocompleteViewController, didSelectHistoryItem: HistoryItem)
}

class AutocompleteViewController: UIViewController, UICollectionViewDelegate
{
    public var historyItems: [HistoryItem] = [] {
        didSet {
            var snapshot = dataSource.snapshot()
            snapshot.deleteAllItems()
            snapshot.appendSections([ .HistoryItems ])
            snapshot.appendItems(historyItems, toSection: .HistoryItems)
            dataSource.apply(snapshot, animatingDifferences: false)
        }
    }
    
    public weak var delegate: AutocompleteViewControllerDelegate?
    
    private enum Section: Int {
        case HistoryItems
    }
    
    override var canBecomeFirstResponder: Bool { true }
    
    public let collectionView: UICollectionView
    private let dataSource: UICollectionViewDiffableDataSource<Section, HistoryItem>
    
    init() {
        let listConfiguration = UICollectionLayoutListConfiguration(appearance: .insetGrouped)
        let listLayout = UICollectionViewCompositionalLayout.list(using: listConfiguration)
        collectionView = UICollectionView(frame: .zero, collectionViewLayout: listLayout)
        
        let cellRegistry = UICollectionView.CellRegistration<UICollectionViewListCell, HistoryItem> { (cell, indexPath, item) in
            var config = cell.defaultContentConfiguration()
            config.text = item.title
            config.secondaryText = item.url.absoluteString
            cell.contentConfiguration = config
        }
        
        dataSource = UICollectionViewDiffableDataSource<Section, HistoryItem>(collectionView: collectionView, cellProvider:
        { (collectionView, indexPath, item) -> UICollectionViewCell? in
            collectionView.dequeueConfiguredReusableCell(using: cellRegistry, for: indexPath, item: item)
        })
        
        super.init(nibName: nil, bundle: nil)
        
        collectionView.delegate = self
        view.backgroundColor = .systemBackground
    }
    
    required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
    
    override func loadView() {
        self.view = collectionView
    }
    
    override var keyCommands: [UIKeyCommand]? {
        [
            UIKeyCommand(action: #selector(self.selectNextItem), input: UIKeyCommand.inputDownArrow),
            UIKeyCommand(action: #selector(self.selectPreviousItem), input: UIKeyCommand.inputUpArrow),
            UIKeyCommand(action: #selector(self.commitSelectedItem), input: "\r"), // this is stupid... 
        ]
    }
    
    override func becomeFirstResponder() -> Bool {
        let result = super.becomeFirstResponder()
        if result {
            let firstIndex = IndexPath(row: 0, section: 0)
            collectionView.selectItem(at: firstIndex, animated: false, scrollPosition: .top)
        }
        
        return result
    }
    
    private func selectItem(inDirection direction: Int) {
        if let selectedIndex = collectionView.indexPathsForSelectedItems?.first {
            let nextRow = (selectedIndex.row + direction)
            if nextRow < dataSource.snapshot().numberOfItems && nextRow >= 0 {
                let nextIndexPath = IndexPath(row: nextRow, section: 0)
                collectionView.selectItem(at: nextIndexPath, animated: false, scrollPosition: .centeredVertically)
            }
        }
    }
    
    @objc
    private func selectNextItem(_ sender: Any?) {
        selectItem(inDirection: 1)
    }
    
    @objc
    private func selectPreviousItem(_ sender: Any?) {
        selectItem(inDirection: -1)
    }
    
    @objc
    private func commitSelectedItem(_ sender: Any?) {
        if let selectedIndex = collectionView.indexPathsForSelectedItems?.first,
           let item = dataSource.itemIdentifier(for: selectedIndex)
        {
            delegate?.autocompleteController(self, didSelectHistoryItem: item)
        }
    }
    
    // MARK: UICollectionViewDelegate
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        collectionView.deselectItem(at: indexPath, animated: true)
        
        if let item = dataSource.itemIdentifier(for: indexPath) {
            delegate?.autocompleteController(self, didSelectHistoryItem: item)
        }
    }
}
