import UIKit

/// unit view delegate protocol
protocol JednotkyViewDelegate: AnyObject {
    func segueToUnit(id: String)
    func segueToPerson(id: String)
}

/// unit view
class JednotkyView: UIView {
    
    weak var delegate: JednotkyViewDelegate?
    var viewModel: JednotkaViewModelProtocol? {
        didSet {
            guard let viewModel = viewModel else { return }
            if viewModel.loading {
                activityIndicator.startAnimating()
            } else {
                activityIndicator.stopAnimating()
            }
            headerView.title.text = viewModel.detail?.DisplayName
            tableView.reloadData()
        }
    }
    
    private let activityIndicator: UIActivityIndicatorView = {
        let view = UIActivityIndicatorView()
        view.translatesAutoresizingMaskIntoConstraints = false
        view.style = .large
        view.color = scoutBlue
        view.startAnimating()
        return view
    }()
    
    private let tableView: UITableView = {
        let view = UITableView(frame: .zero, style: .insetGrouped)
        view.translatesAutoresizingMaskIntoConstraints = false
        view.tableFooterView = UIView()
        view.rowHeight = UITableView.automaticDimension
        return view
    }()
    
    let headerView: JednotkaHeaderView = {
        let view = JednotkaHeaderView()
        view.frame.size.height = 120
        return view
    }()
    
    /// initialization function
    /// - Parameter frame: frame
    override init(frame: CGRect) {
        super.init(frame: frame)
        addSubview(tableView)
        addSubview(activityIndicator)
        tableView.delegate = self
        tableView.dataSource = self
        tableView.tableHeaderView = headerView
        tableView.register(OsobaTableViewCell.self, forCellReuseIdentifier: OsobaTableViewCell.cellIdentifier)
        setupConstraints()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    /// function that sets up constraints for view
    private func setupConstraints() {
        NSLayoutConstraint.activate([
            activityIndicator.centerYAnchor.constraint(equalTo: centerYAnchor),
            activityIndicator.centerXAnchor.constraint(equalTo: centerXAnchor),
            
            tableView.leadingAnchor.constraint(equalTo: leadingAnchor),
            tableView.topAnchor.constraint(equalTo: topAnchor),
            tableView.trailingAnchor.constraint(equalTo: trailingAnchor),
            tableView.bottomAnchor.constraint(equalTo: bottomAnchor)
        ])
    }
}

extension JednotkyView: UITableViewDelegate, UITableViewDataSource {
    
    /// function that return number of sections
    /// - Parameter tableView: tableview
    /// - Returns: number of sections
    func numberOfSections(in tableView: UITableView) -> Int {
        viewModel?.sections.count ?? 0
    }
    
    /// function that returns number of table rows for given section
    /// - Parameters:
    ///   - tableView: table view
    ///   - section: section
    /// - Returns: number of rows
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        viewModel?.sections[section].count ?? 0
    }
    
    /// function that returns the height for footer in section
    /// - Parameters:
    ///   - tableView: tableview
    ///   - section: section
    /// - Returns: height of footer view for section
    func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
        0
    }
    
    /// function that returns header based on section section
    /// - Parameters:
    ///   - tableView: tableview
    ///   - section: section
    /// - Returns: header view for section
    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let view = OsobaSectionHeader()
        switch viewModel?.sections[section].first {
        case is UnitContact:
            view.title.text = "Kontakty"
        case is Address:
            view.title.text = "Adresa Jednotky"
        case is PostalAddress:
            view.title.text = "Korespondenční adresa"
        case is FunctionUnit:
            view.title.text = "Osoby ve funkci"
        case is UnitTree:
            view.title.text = "Podžízená OJ"
        case is UnitDetailResult:
            view.title.text = "Nadřízená jednotky"
        default:
            return nil
        }
        return view
    }
    
    /// function that returns table view cell for given path
    /// - Parameters:
    ///   - tableView: tableview
    ///   - indexPath: index path
    /// - Returns: table view cell for given path
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let item = viewModel?.sections[indexPath.section][indexPath.row],
            let cell = tableView.dequeueReusableCell(withIdentifier: OsobaTableViewCell.cellIdentifier) as? OsobaTableViewCell else { return UITableViewCell() }
        
        switch item {
        case let info as Address:
            cell.title.text = info.AddressType
            cell.subtitle.text = info.Value
        case let info as UnitContact:
            cell.title.text = info.ContactType
            cell.subtitle.text = info.Value
        case let info as PostalAddress:
            cell.title.text = info.AddressType
            cell.subtitle.text = info.Value
        case let info as FunctionUnit:
            cell.title.text = info.Person
            cell.subtitle.text = info.FunctionType
        case let info as UnitTree:
            cell.title.text = info.Unit
            cell.subtitle.text = info.RegistrationNumber
        case let info as UnitDetailResult:
            cell.title.text = info.DisplayName
            cell.subtitle.text = nil
        default:
            break
        }
        
        return cell
    }
    
    /// function that gets called when cell is selected
    /// - Parameters:
    ///   - tableView: tableview
    ///   - indexPath: index that was selected
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        guard let item = viewModel?.sections[indexPath.section][indexPath.row] else { return }
        var id: String = ""
        switch item {
        case let info as FunctionUnit:
            delegate?.segueToPerson(id: info.ID_Person)
            return
        case let info as UnitTree:
            id = info.ID_Unit
        case let info as UnitDetailResult:
            id = info.ID
        default:
            return
        }
        guard id != "" else { return }
        delegate?.segueToUnit(id: id)
    }
    
}
