//
//  SectionListTemplate.swift
//  MVMCoreUI
//
//  Created by Scott Pfeil on 9/25/20.
//  Copyright © 2020 Verizon Wireless. All rights reserved.
//


open class SectionListTemplate: MoleculeListTemplate {
    
    public var sectionMoleculesInfo: [(header: MoleculeInfo?, footer: MoleculeInfo?, rows: [MoleculeInfo])]?

    open override func viewDidLoad() {
        super.viewDidLoad()
        tableView.sectionHeaderHeight = UITableView.automaticDimension
    }
    
    override func setup() {
        // Create quick reference
        var sectionList: [(header: MoleculeInfo?, footer: MoleculeInfo?, rows: [MoleculeInfo])] = []
        
        if let sections = (templateModel as? SectionListTemplateModel)?.sections {
            for section in sections {
                let header = createMoleculeInfo(with: section.header)
                let footer = createMoleculeInfo(with: section.footer)
                var rows: [MoleculeInfo] = []
                for row in section.rows {
                    if let rowInfo = createMoleculeInfo(with: row) {
                        rows.append(rowInfo)
                    }
                }
                sectionList.append((header: header, footer: footer, rows: rows))
            }
        }
        
        sectionMoleculesInfo = sectionList.count > 0 ? sectionList : nil
    }
    
    override func getMoleculeInfo(for indexPath: IndexPath) -> MoleculeInfo? {
        sectionMoleculesInfo?[indexPath.section].rows[indexPath.row]
    }
    
    open override func createTableView() -> TableView {
        let tableView = TableView(frame: .zero, style: .plain)
        tableView.backgroundColor = .clear
        tableView.separatorStyle = UITableViewCell.SeparatorStyle.none
        tableView.delegate = self
        tableView.dataSource = self
        tableView.insetsContentViewsToSafeArea = false
        return tableView
    }
    
    // For subclassing the model.
    open override func decodeTemplate(using decoder: JSONDecoder, from data: Data) throws -> SectionListTemplateModel {
        try decoder.decode(SectionListTemplateModel.self, from: data)
    }
    
    open override func registerWithTable() {
        super.registerWithTable()
        guard let sections = sectionMoleculesInfo else { return }
        for section in sections {
            if let header = section.header {
                tableView.register(header.class, forHeaderFooterViewReuseIdentifier: header.identifier)
            }
            if let footer = section.footer {
                tableView.register(footer.class, forHeaderFooterViewReuseIdentifier: footer.identifier)
            }
            for row in section.rows {
                tableView.register(row.class, forCellReuseIdentifier: row.identifier)
            }
        }
    }
    
    public func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat {
        guard let moleculeInfo = sectionMoleculesInfo?[section].header else {
            return CGFloat.leastNormalMagnitude
        }
        let estimatedHeight = (moleculeInfo.class as? MoleculeViewProtocol.Type)?.estimatedHeight(with: moleculeInfo.molecule, delegateObject() as? MVMCoreUIDelegateObject)
        return estimatedHeight ?? 80
    }
    
    public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        guard (sectionMoleculesInfo?[section].header) != nil else {
            return CGFloat.leastNormalMagnitude
        }
        return UITableView.automaticDimension
    }
    
    public func tableView(_ tableView: UITableView, estimatedHeightForFooterInSection section: Int) -> CGFloat {
        guard let moleculeInfo = sectionMoleculesInfo?[section].footer else {
            return CGFloat.leastNormalMagnitude
        }
        let estimatedHeight = (moleculeInfo.class as? MoleculeViewProtocol.Type)?.estimatedHeight(with: moleculeInfo.molecule, delegateObject() as? MVMCoreUIDelegateObject)
        return estimatedHeight ?? 80
    }
    
    public func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
        guard (sectionMoleculesInfo?[section].footer) != nil else {
            return CGFloat.leastNormalMagnitude
        }
        return UITableView.automaticDimension
    }
    
    public func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        guard let sectionInfo = sectionMoleculesInfo?[section],
              let headerInfo = sectionInfo.header
        else { return nil }
        
        let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: headerInfo.identifier)
        (header as? MoleculeViewProtocol)?.reset()
        (header as? MoleculeViewProtocol)?.set(with: headerInfo.molecule, delegateObjectIVar, nil)
        (header as? MVMCoreViewProtocol)?.updateView(tableView.bounds.width)
        // Neded to fix an apple defect where the cell is not the correct size on certain devices for certain cells
        header?.layoutIfNeeded()
        return header
    }
    
    public func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
        guard let sectionInfo = sectionMoleculesInfo?[section],
              let footerInfo = sectionInfo.footer
        else { return nil }
        
        let footer = tableView.dequeueReusableHeaderFooterView(withIdentifier: footerInfo.identifier)
        (footer as? MoleculeViewProtocol)?.reset()
        (footer as? MoleculeViewProtocol)?.set(with: footerInfo.molecule, delegateObjectIVar, nil)
        (footer as? MVMCoreViewProtocol)?.updateView(tableView.bounds.width)
        // Neded to fix an apple defect where the cell is not the correct size on certain devices for certain cells
        footer?.layoutIfNeeded()
        return footer
    }
    
    open override func getNumberOfSections() -> Int {
        sectionMoleculesInfo?.count ?? 0
    }
    
    open override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        sectionMoleculesInfo?[section].rows.count ?? 0
    }
}
