import Foundation
import SwiftUI

extension AuthResponse.DeleteStatus {
    var title: String? {
        switch self {
        case .notRequested:
            return nil
        case .pendingConfirmation:
            return "Deletion pending - email confirmation required"
        case .pendingDelete:
            return "Deletion pending"
        }
    }
}

extension Post {
    var shortDateString: String? {
        guard let date = date else {
            return nil
        }
        return DateFormatter.short.string(from: date)
    }
    
    var longDateString: String? {
        guard let date = date else {
            return nil
        }
        return DateFormatter.long.string(from: date)
    }
    
    var authorString: String? {
        let prefix = "By "
        var authors = self.author
        
        guard let lastAuthor = authors.popLast() else {
            return nil
        }
        
        if authors.isEmpty {
            return prefix + lastAuthor.name
        }
        
        return prefix
        + (authors.compactMap({$0.name}).joined(separator: ", "))
        + " and "
        + lastAuthor.name
    }
    
    var dateAuthorString: String {
        let date = self.shortDateString
        let author = self.authorString
        
        return [date, author].compactMap { $0 }.joined(separator: " | ")
    }
    
    var longDateAuthorString: String {
        let date = self.longDateString
        let author = self.authorString
        
        return [date, author].compactMap { $0 }.joined(separator: " | ")
    }
    
    func eventForDate(_ date: Date) -> Event? {
        events.first(where: { Calendar.current.isDate($0.date, inSameDayAs: date) })
    }
    
    func eventStartTimeForDate(_ date: Date, withPrefix: Bool) -> String? {
        guard let event = eventForDate(date) else {
            return nil
        }
        
        return event.startTimeString(withPrefix: withPrefix)
    }
    
    func eventEndTimeForDate(_ date: Date) -> String? {
        guard let event = eventForDate(date) else {
            return nil
        }
        
        return event.endTimeString()
    }
    
    var summary: PostSummary {
        PostSummary(id: self.id,
                    date: self.date,
                    dateGMT: self.dateGMT,
                    slug: self.slug,
                    type: self.type,
                    link: self.link,
                    title: self.title.rendered,
                    author: self.author,
                    commentCount: self.commentCount,
                    commentStatus: self.commentStatus,
                    latestCommentDate: self.latestComments.first?.date,
                    primaryTopic: self.primaryTopic)
    }
    
    var isHydrated: Bool {
        allComments != nil && banners != nil
    }
}

extension Post: Comparable {
    public static func < (lhs: Post, rhs: Post) -> Bool {
        if let lhsDate = lhs.date, let rhsDate = rhs.date {
            return lhsDate < rhsDate
        }
        
        if let lhsDateModified = lhs.modified, let rhsDateModified = rhs.modified {
            return lhsDateModified < rhsDateModified
        }
        
        return lhs.title.rendered < rhs.title.rendered
    }
    
    
}

extension Post.Event {
    var longDateString: String {
        return DateFormatter.long.string(from: self.date)
    }
    
    var startDate: Date {
        guard let timeStart = self.timeStart else {
            return date
        }
        
        let timeComponents = Array(timeStart.split(separator: ":")).compactMap { Int($0) ?? 0 }
        guard timeComponents.count >= 2,
              let dateWithTime = Calendar.current.date(bySettingHour: timeComponents[0], minute: timeComponents[1], second: 0, of: date)
        else {
            return date
        }
        
        return dateWithTime
    }
    
    func startTimeString(withPrefix: Bool) -> String? {
        let formatted = DateFormatter.time.string(from: startDate)
        
        if !withPrefix {
            return formatted
        }
        
        if endTimeString() != nil {
            return formatted
        }
        
        return "From\n\(formatted)"
    }
    
    var endDate: Date? {
        guard let timeEnd = self.timeEnd else {
            return nil
        }
        
        let timeComponents = Array(timeEnd.split(separator: ":")).compactMap { Int($0) ?? 0 }
        guard timeComponents.count >= 2,
              let dateWithTime = Calendar.current.date(bySettingHour: timeComponents[0], minute: timeComponents[1], second: 0, of: date)
        else {
            return nil
        }
        
        return dateWithTime
    }
    
    func endTimeString() -> String? {
        guard let dateWithTime = endDate else {
            return nil
        }
        
        return DateFormatter.time.string(from: dateWithTime)
    }
}

extension PostSummary {
    var shortDateString: String {
        guard let date = date else {
            return ""
        }
        return DateFormatter.short.string(from: date)
    }
    
    var longDateString: String {
        guard let date = date else {
            return ""
        }
        return DateFormatter.long.string(from: date)
    }

    var authorString: String? {
        guard let aString = authorStringNoPrefix else {
            return nil
        }
        
        return "By " + aString
    }
    
    var authorStringNoPrefix: String? {
        var authors = self.author
        
        guard let lastAuthor = authors.popLast() else {
            return nil
        }
        
        if authors.isEmpty {
            return lastAuthor.name
        }
        
        return (authors.compactMap({$0.name}).joined(separator: ", ")) + " and " + lastAuthor.name
    }
    
    var dateAuthorString: String {
        let date = self.longDateString
        let author = self.authorString
        
        return [date, author].compactMap { $0 }.joined(separator: " | ")
    }
}

extension Topic {
    var topicRef: TopicRef {
        return TopicRef(id: self.id, name: self.name)
    }
    
    var backgroundColor: Color {
        return Color(self.colour) ?? ColorName.tint.color
    }
    
    var foregroundColor: Color {
        return Color(self.textColour) ?? ColorName.textOnTint.color
    }
}

extension EventCalendar {
    static var empty: EventCalendar {
        EventCalendar(schedule: [], posts: [])
    }
    
    func postsForTimeSlot(_ timeSlot: TimeSlot, showRecurring: Bool = true) -> [Post] {
        let posts = posts.filter { timeSlot.postIds.contains("\($0.id)") }
        if showRecurring {
            return posts
        }
        
        return posts.filter { $0.events.count == 1 }
    }
    
    func timeSlotsForDate(_ date: Date) -> [TimeSlot] {
        self.schedule.filter { Calendar.current.isDate($0.time, inSameDayAs: date) }
    }
    
    var validDates: [Date: [TimeSlot]] {
        let today = Date()
        var validDates: [Date: [TimeSlot]] = [:]
        
        for d in 0..<365 {
            guard let date = Calendar.current.date(byAdding: .day, value: d, to: today) else {
                continue
            }
            
            let timeslots = timeSlotsForDate(date)
            if !timeslots.isEmpty {
                validDates[date] = timeslots
            }
        }
        
        return validDates
    }
}

extension Banner {
    func stripHeading() -> Banner {
        Banner(name: self.name,
               hideShade: self.hideShade,
               heading: self.subheading,
               subheading: nil,
               link: self.link,
               banner: self.banner,
               logo: self.logo,
               headingSize: self.headingSize,
               subheadingSize: self.subheadingSize)
    }
}

extension Feedback {
    init(email: String?, message: String) {
        self.email = email
        self.message = message
        self.version = "\(Bundle.versionNumber); \(UIDevice.current.systemName) \(UIDevice.current.systemVersion), \(UIDevice.current.name)"
    }
}
