//
//  SettingsCellFactory.swift
//  1Weather
//
//  Created by Dmitry Stepanets on 26.03.2021.
//

import UIKit
import Localize_Swift

public enum SettingsRow {
    case theme
    case temperature
    case wind
    case pressure
    case distance
    case language
    case manageNotifications
    case locationAccess
    
    var roundedCorners:CACornerMask {
        switch self {
        case .theme:
            return [.layerMinXMinYCorner, .layerMinXMaxYCorner, .layerMaxXMaxYCorner, .layerMaxXMinYCorner]
        case .temperature:
            return [.layerMinXMinYCorner, .layerMaxXMinYCorner]
        case .distance:
            return [.layerMinXMaxYCorner, .layerMaxXMaxYCorner]
        case .language:
            return [.layerMinXMinYCorner, .layerMinXMaxYCorner, .layerMaxXMaxYCorner, .layerMaxXMinYCorner]
        case .manageNotifications:
            return [.layerMinXMinYCorner, .layerMaxXMinYCorner]
        case .locationAccess:
            return [.layerMinXMaxYCorner, .layerMaxXMaxYCorner]
        default:
            return []
        }
    }
    
    var localizedName:String {
        switch self {
        case .theme:
            return ""
        case .temperature:
            return "settings.unit.temp".localized()
        case .wind:
            return "settings.unit.wind".localized()
        case .pressure:
            return "settings.unit.pressure".localized()
        case .distance:
            return "settings.unit.distance".localized()
        case .language:
            return "settings.language".localized()
        case .manageNotifications:
            return "settings.manageNotifications".localized()
        case .locationAccess:
            return "settings.locationAccess".localized()
        }
    }
}

public enum SettingsSection {
    case theme
    case units
    case language
    case other
    
    var localized:String {
        switch self {
        case .theme:
            return "settings.theme".localized()
        case .units:
            return "settings.units".localized()
        default:
            return ""
        }
    }
}

private struct SettingsDataSource {
    let section:SettingsSection
    let rows:[SettingsRow]
}

class SettingsCellFactory: CellFactoryProtocol {
    //Private
    private let viewModel:SettingsViewModel
    private let sections:[SettingsDataSource] = [SettingsDataSource(section: .theme, rows: [.theme]),
                                                 SettingsDataSource(section: .units, rows: [.temperature, .wind, .pressure, .distance]),
                                                 SettingsDataSource(section: .language, rows: [.language]),
                                                 SettingsDataSource(section: .other, rows: [.manageNotifications, .locationAccess])]
    
    //Public
    init(viewModel:SettingsViewModel) {
        self.viewModel = viewModel
    }
    
    public var numberOfSections: Int {
        return sections.count
    }
    
    public func numberOfRows(inSection section: Int) -> Int {
        return sections[section].rows.count
    }
    
    public func registerCells(on tableView: UITableView) {
        self.registerCell(type: SettingsThemeCell.self, tableView: tableView)
        self.registerCell(type: SettingsCell.self, tableView: tableView)
    }
    
    public func cellFromTableView(tableView: UITableView, indexPath: IndexPath) -> UITableViewCell {
        let sectionType = sections[indexPath.section].section
        
        switch sectionType {
        case .theme:
            let cell = self.dequeueReusableCell(type: SettingsThemeCell.self, tableView: tableView, indexPath: indexPath)
            cell.configure(settings: viewModel.settings)
            return cell
        case .units:
            let rowType = sections[indexPath.section].rows[indexPath.row]
            let cell = dequeueReusableCell(type: SettingsCell.self, tableView: tableView, indexPath: indexPath)
            
            var name = ""
            var symbol = ""
            switch rowType {
            case .temperature:
                name = viewModel.settings.temperatureType.name
                symbol = viewModel.settings.temperatureType.symbol
            case .wind:
                name = viewModel.settings.windSpeedType.name
                symbol = viewModel.settings.windSpeedType.symbol
            case .pressure:
                name = viewModel.settings.pressureType.name
                symbol = viewModel.settings.pressureType.symbol
            case .distance:
                name = viewModel.settings.distanceType.name
                symbol = viewModel.settings.distanceType.symbol
            default:
                break
            }
            cell.configure(settingsName: rowType.localizedName,
                           selectedValue: "\(name) (\(symbol))",
                           roundCorners: rowType.roundedCorners)
            return cell
        case .language:
            let cell = dequeueReusableCell(type: SettingsCell.self, tableView: tableView, indexPath: indexPath)
            cell.configure(settingsName: SettingsRow.language.localizedName,
                           selectedValue: Localize.displayNameForLanguage(Localize.currentLanguage()),
                           roundCorners: SettingsRow.language.roundedCorners)
            return cell
        case .other:
            let rowType = sections[indexPath.section].rows[indexPath.row]
            let cell = dequeueReusableCell(type: SettingsCell.self, tableView: tableView, indexPath: indexPath)
            
            switch rowType {
            case .manageNotifications:
                cell.configure(settingsName: rowType.localizedName, selectedValue: "", roundCorners: rowType.roundedCorners)
            case .locationAccess:
                cell.configure(settingsName: rowType.localizedName, selectedValue: "--", roundCorners: rowType.roundedCorners)
            default:
                break
            }
            return cell
        }
    }
    
    public func sectionTypeAt(indexPath:IndexPath) -> SettingsSection {
        return sections[indexPath.section].section
    }
    
    public func rowTypeAt(indexPath:IndexPath) -> SettingsRow {
        return sections[indexPath.section].rows[indexPath.row]
    }
}
