//
//  ForecastCellFactory.swift
//  1Weather
//
//  Created by Dmitry Stepanets on 10.03.2021.
//

import UIKit

private enum DailyForecastCellType:Int, CaseIterable {
    case forecast = 0
    case forecastInfo
//    case forecast
//    case conditions
//    case precipitation
//    case dayTime
    case sun
    case moon
}

private enum HourlyForecastCellType: Int, CaseIterable {
    case day
    case tempInfo
    case precipitation
    case wind
}

class ForecastCellFactory: CellFactoryProtocol {
    //Private
    private let forecastViewModel:ForecastViewModel
    private var currentTimePeriod = TimePeriod.daily
    
    //Public
    var numberOfSections: Int {
        return 1
    }
    
    public func numberOfRows(inSection section: Int) -> Int {
        return currentTimePeriod == .daily ? DailyForecastCellType.allCases.count : HourlyForecastCellType.allCases.count
    }
    
    public init(viewModel: ForecastViewModel) {
        self.forecastViewModel = viewModel
    }
    
    public func setTimePeriod(timePeriod:TimePeriod) {
        self.currentTimePeriod = timePeriod
    }
    
    public func registerCells(on tableView:UITableView) {
        registerCell(type: ForecastDailyCell.self, tableView: tableView)
        registerCell(type: ForecastDayCell.self, tableView: tableView)
        registerCell(type: ForecastHourlyCell.self, tableView: tableView)
        registerCell(type: ForecastInfoCell.self, tableView: tableView)
        registerCell(type: PrecipitationCell.self, tableView: tableView)
        registerCell(type: ForecastWindSpeedCell.self, tableView: tableView)
        registerCell(type: SunPhaseCell.self, tableView: tableView)
        registerCell(type: MoonPhaseCell.self, tableView: tableView)
    }
    
    public func cellFromTableView(tableView:UITableView, indexPath:IndexPath) -> UITableViewCell {
        switch currentTimePeriod {
        case .daily:
            return dailyCellFor(tableView: tableView, indexPath: indexPath)
        case .hourly:
            return hourlyCellFor(tableView: tableView, indexPath: indexPath)
        }
    }
    
    public func willDisplay(cell:UITableViewCell) {
        switch cell {
        case let sunCell as SunPhaseCell:
            sunCell.updateSunPosition()
        case let moonCell as MoonPhaseCell:
            moonCell.updateMoonPosition()
        default:
            break
        }
    }
    
    //Private
    private func dailyCellFor(tableView:UITableView, indexPath:IndexPath) -> UITableViewCell {
        guard let cellType = DailyForecastCellType(rawValue: indexPath.row) else {
            return UITableViewCell()
        }
        
        switch cellType {
        case .forecast:
            let cell = dequeueReusableCell(type: ForecastDailyCell.self, tableView: tableView, indexPath: indexPath)
            cell.delegate = self
            
            if let daily = forecastViewModel.location?.daily {
                cell.configure(daily: daily,
                               offset: forecastViewModel.offsetHolder.currentOffset,
                               selectedButtonIndex: forecastViewModel.selectedDailyWeatherIndex)
            }
            return cell
        case .forecastInfo:
            let cell = dequeueReusableCell(type: ForecastInfoCell.self, tableView: tableView, indexPath: indexPath)
            if let daily = forecastViewModel.selectedDailyWeather {
                cell.configure(dailyWeather: daily)
            }
            
            return cell
        case .sun:
            let cell = dequeueReusableCell(type: SunPhaseCell.self, tableView: tableView, indexPath: indexPath)
            if let loc = forecastViewModel.location {
                cell.configure(with: loc)
            }
            return cell
        case .moon:
            let cell = dequeueReusableCell(type: MoonPhaseCell.self, tableView: tableView, indexPath: indexPath)
            if let loc = forecastViewModel.location {
                cell.configure(with: loc)
            }
            return cell
        }
    }
    
    private func hourlyCellFor(tableView:UITableView, indexPath:IndexPath) -> UITableViewCell {
        guard let cellType = HourlyForecastCellType(rawValue: indexPath.row) else {
            return UITableViewCell()
        }
        
        switch cellType {
        case .day:
            let cell = dequeueReusableCell(type: ForecastDayCell.self, tableView: tableView, indexPath: indexPath)
            if let today = forecastViewModel.location?.today{
                cell.configure(today: today)
            }
            return cell
        case .tempInfo:
            let cell = dequeueReusableCell(type: ForecastHourlyCell.self, tableView: tableView, indexPath: indexPath)
            if let hourly = forecastViewModel.location?.hourly {
                cell.configure(hourly: hourly)
            }
            return cell
        case .precipitation:
            let cell = dequeueReusableCell(type: PrecipitationCell.self, tableView: tableView, indexPath: indexPath)
            if let hourly = forecastViewModel.location?.hourly {
                cell.configure(with: hourly)
            }
            return cell
        case .wind:
            let cell = dequeueReusableCell(type: ForecastWindSpeedCell.self, tableView: tableView, indexPath: indexPath)
            if let hourly = forecastViewModel.location?.hourly {
                cell.configure(with: hourly)
            }
            return cell
        }
    }
}

//MARK:- ForecastTimePeriodCell Delegate
extension ForecastCellFactory: ForecastDailyCellDelegate {
    func timePeriodCell(cell: ForecastDailyCell, didSelectButtonAt index: Int) {
        forecastViewModel.selectDailyWeatherAt(index: index)
    }
    
    func timePeriodCell(cell: ForecastDailyCell, offsetDidChage offset: CGFloat) {
        forecastViewModel.offsetHolder.update(offset: offset)
    }
}
