import UIKit
import RxSwift

class RegionsDataSourse: UITableViewDiffableDataSource<VehicleRegion, Int> {
    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return snapshot().sectionIdentifiers[section].name
    }
}

class RegionsController: UIViewController, UISearchResultsUpdating, UITableViewDelegate {
    
    @IBOutlet weak var tableView: UITableView!
    
    var regions: [VehicleRegion] = []
    var regionsFiltered: [VehicleRegion] = []
    var done = false
    var onDone: (([Int]?) -> Void)?
    var regionCodes: [Int] = []
    var datasource: RegionsDataSourse!
    
    let searchController = UISearchController(searchResultsController: nil)
    let bag = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        searchController.searchResultsUpdater = self
        searchController.obscuresBackgroundDuringPresentation = false
        searchController.searchBar.placeholder = NSLocalizedString("Search regions", comment: "Search field placeholder")
        navigationItem.searchController = searchController
        navigationItem.hidesSearchBarWhenScrolling = false
        definesPresentationContext = true
        
        self.datasource = RegionsDataSourse(tableView: self.tableView) { tableView, indexPath, code -> UITableViewCell? in
            var cell = tableView.dequeueReusableCell(withIdentifier: "RegionCell")
            if cell == nil {
                cell = UITableViewCell(style: .value1, reuseIdentifier: "RegionCell")
            }
            
            let selectedIndexPaths = tableView.indexPathsForSelectedRows
            let rowIsSelected = selectedIndexPaths != nil && selectedIndexPaths!.contains(indexPath)
            cell?.accessoryType = rowIsSelected ? .checkmark : .none
            cell?.selectionStyle = .none
            
            cell?.textLabel?.text = String(code)
            return cell
        }
        
        Api.getRegions().observeOn(MainScheduler.instance).subscribe(onSuccess: { regions in
            self.regions = regions
            self.regionsFiltered = regions
            self.updateTableView()
            self.applySelection()
        }, onError: { error in
            print("Get regions error: ", error)
        }).disposed(by: self.bag)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        if self.done {
            self.onDone?(self.regionCodes)
        }
    }
    
    @IBAction func onDone(_ sender: UIBarButtonItem) {
        self.done = true
        self.navigationController?.popViewController(animated: true)
    }
    
    func updateTableView() {
        var snapshot = NSDiffableDataSourceSnapshot<VehicleRegion, Int>()
        snapshot.appendSections(self.regionsFiltered)
        for region in self.regionsFiltered {
            snapshot.appendItems(region.codes, toSection: region)
        }
        self.datasource.apply(snapshot);
    }
    
    func applySelection() {
        self.regionCodes.forEach { code in
            if let section = self.regionsFiltered.firstIndex(where: { $0.codes.contains(code) }) {
                if let row = self.regionsFiltered[section].codes.firstIndex(of: code) {
                    let indexPath = IndexPath(row: row, section: section)
                    self.tableView.selectRow(at: indexPath, animated: false, scrollPosition: .middle)
                    let cell = tableView.cellForRow(at: indexPath)!
                    cell.accessoryType = .checkmark
                }
            }
        }
    }
    
    // MARK: - UITableViewDelegate
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let cell = tableView.cellForRow(at: indexPath)!
        cell.accessoryType = .checkmark
        
        if let codeStr = cell.textLabel?.text, let code = Int(codeStr) {
            if !self.regionCodes.contains(code) {
                self.regionCodes.append(code)
            }
        }
    }

    func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
        let cell = tableView.cellForRow(at: indexPath)!
        cell.accessoryType = .none
        
        if let codeStr = cell.textLabel?.text, let code = Int(codeStr) {
            self.regionCodes.removeAll(where: { $0 == code })
        }
    }
    
    // MARK: - UISearchResultsUpdating
    
    func updateSearchResults(for searchController: UISearchController) {
        let newQuery = searchController.searchBar.text?.uppercased() ?? ""
        
        if newQuery.isEmpty {
            self.regionsFiltered = self.regions
        } else {
            self.regionsFiltered = self.regions.filter { $0.name.lowercased().contains(newQuery.lowercased()) }
        }
        self.updateTableView()
        self.applySelection()
    }
}
