//
//  ChartDataBuildable.swift
//  Feels
//
//  Created by Trey Tartt on 1/17/22.
//

import SwiftUI

typealias Year = Int
typealias Month = Int

protocol ChartDataBuildable {
    associatedtype ChartType: ChartViewItemBuildable
    // [Year: [Month: [View]]
    func buildGridData(withData data: [MoodEntry]) -> [Year: [Month: [ChartType]]]
}

extension ChartDataBuildable {
    public func buildGridData(withData data: [MoodEntry]) ->  [Year: [Month: [ChartType]]] {
        var returnData = [Int: [Int: [ChartType]]]()
        
        if let earliestEntry = data.first,
           let lastEntry = data.last {
            
            let calendar = Calendar.current
            let components = calendar.dateComponents([.year], from: earliestEntry.forDate!)
            let earliestYear = components.year!
            
            let latestComponents = calendar.dateComponents([.year], from: lastEntry.forDate!)
            let latestYear = latestComponents.year!
            
            for year in earliestYear...latestYear {
                var allMonths = [Int: [ChartType]]()
                
                // add back in if months header has leading (-1, ""),
                // and add back gridItem
                //                var dayViews = [DayChartView]()
                //                for day in 0...32 {
                //                    let view = DayChartView(color: Mood.missing.color,
                //                                           weekDay: 2,
                //                                           viewType: .text(String(day+1)))
                //                    dayViews.append(view)
                //                }
                //                allMonths[0] = dayViews
                
                for month in (1...12) {
                    var components = DateComponents()
                    components.month = month
                    components.year = year
                    let startDateOfMonth = Calendar.current.date(from: components)!
                    
                    let items = data.filter({ entry in
                        let components = calendar.dateComponents([.month, .year], from: startDateOfMonth)
                        let entryComponents = calendar.dateComponents([.month, .year], from: entry.forDate!)
                        return (components.month == entryComponents.month && components.year == entryComponents.year)
                    })
                    
                    allMonths[month] = createViewFor(monthEntries: items, forMonth: startDateOfMonth)
                }
                returnData[year] = allMonths
            }
        }
        return returnData
    }
    
    private func createViewFor(monthEntries: [MoodEntry], forMonth month: Date) -> [ChartType] {
        var filledOutArray = [ChartType]()
        
        let calendar = Calendar.current
        let range = calendar.range(of: .day, in: .month, for: month)!
        let numDays = range.count
        
        for day in 1...numDays {
            if let item = monthEntries.filter({ entry in
                let components = calendar.dateComponents([.day], from: entry.forDate!)
                let date = components.day
                return day == date
            }).first {
                let view = ChartType(color: item.mood.color,
                                     weekDay: Int(item.weekDay),
                                     viewType: .square)
                filledOutArray.append(view)
            } else {
                let thisDate = Calendar.current.date(bySetting: .day, value: day, of: month)!
                let view = ChartType(color: Mood.missing.color,
                                     weekDay:  Calendar.current.component(.weekday, from: thisDate),
                                     viewType: .square)
                filledOutArray.append(view)
            }
        }
        
        for _ in filledOutArray.count...32 {
            let view = ChartType(color: Mood.missing.color,
                                 weekDay: 2,
                                 viewType: .cicle)
            filledOutArray.append(view)
        }
        
        return filledOutArray
    }
}

struct DayChartViewChartBuilder: ChartDataBuildable {
    typealias ChartType = DayChartView
}
