import Foundation
import SwiftDate
import DifferenceKit

struct DateSection<T>: Differentiable, DifferentiableSection, Hashable where T: Differentiable & Hashable {
    
	var timestamp: Double = 0
    var header: String
    var elements: [T]
    
    init<C>(source: DateSection<T>, elements: C) where C : Swift.Collection, C.Element == Self.Collection.Element {
        self.timestamp = source.timestamp
        self.header = source.header
        self.elements = Array(elements)
    }
    
    init(original: DateSection, items: [T]) {
        self = original
        self.elements = items
    }
    
    init(timestamp: Double, items: [T]) {
		let formatter = DateFormatter()
		formatter.dateStyle = .medium
		formatter.timeStyle = .medium
		
        let now = DateInRegion(Date(), region: Region.current)
        let monthStart = now.dateAtStartOf(.month)
        let weekStart = now.dateAtStartOf(.weekOfMonth)
		
		let date = Date(timeIntervalSince1970: timestamp)
        let dateInRegion = DateInRegion(date, region: Region.current)
		if dateInRegion.isToday {
			self.header = NSLocalizedString("Today", comment: "")
		}
		else if dateInRegion.isYesterday {
			self.header = NSLocalizedString("Yesterday", comment: "")
		} else if dateInRegion.isAfterDate(weekStart, granularity: .day) {
			formatter.dateFormat = "EEEE"
			self.header = formatter.string(from: date)
		} else if dateInRegion.isAfterDate(monthStart, orEqual: false, granularity: .day) {
			formatter.dateStyle = .medium
			formatter.timeStyle = .none
			self.header = formatter.string(from: date)
		} else {
			formatter.dateFormat = "LLLL yyyy"
			self.header = formatter.string(from: date)
		}
		
        self.timestamp = timestamp
        self.elements = items
    }
    
    mutating func append(_ element: T) {
        self.elements.append(element)
    }
    
    // MARK: - Differentiable
    
    var differenceIdentifier: String {
        return header
    }
    
    func isContentEqual(to source: DateSection<T>) -> Bool {
        return self.differenceIdentifier == source.differenceIdentifier
    }
    
    // MARK: - Hashable
    
    static func == (lhs: DateSection<T>, rhs: DateSection<T>) -> Bool {
        return lhs.timestamp == rhs.timestamp && lhs.elements == rhs.elements
    }
    
    func hash(into hasher: inout Hasher) {
        hasher.combine(self.timestamp)
        hasher.combine(self.elements)
    }
}
