import Foundation
import UIKit

public enum SignInState: Equatable {
    case unknown
    case signedOut
    case error
    case signedIn(response: AuthResponse)
}

public enum RiotError: Error {
    case fetchError
    case submitError
    case authError
    case urlError
    case dataError
}

public struct Banner: Hashable {
    var name: String
    var hideShade: Bool
    var heading: String?
    var subheading: String?
    var link: URL?
    var banner: URL?
    var logo: URL?
    var headingSize: Int?
    var subheadingSize: Int?
}

public enum WebAsset: Hashable {
    enum Key: String {
        case css
        case js
    }
    case css(URL)
    case js(URL)
    
    init?(key: String, url: URL) {
        guard let enumKey = WebAsset.Key(rawValue: key.lowercased()) else {
            return nil
        }
        
        switch enumKey {
        case .css:
            self = .css(url)
        case .js:
            self = .js(url)
        }
    }
}

public struct Rendered: Codable, Hashable {
    public let rendered: String
    public let protected: Bool?
}

public struct Author: Hashable, Equatable, Codable {
    let id: Int
    let name: String
    let avatar: URL?
    let link: URL?
    let bio: String?
}

public struct AuthorResponse: Codable {
    let author: Author
    let posts: [Post]
    let banners: [Banner]
}


public struct TopicRef: Codable, Hashable {
    let id: Int
    let name: String
}

public struct Tag: Codable, Hashable {
    let id: Int
    let name: String
}

public struct Topic: Hashable, Equatable {
    let id: Int
    let name: String
    let slug: String
    let link: URL?
    let colour: String
    let textColour: String
    let children: [Topic]
    let featurePosts: [Post]
}

public struct Thumbnail: Codable, Hashable {
    let square: URL?
    let banner: URL?
}

public struct PolicyPageResponse {
    let pages: [PolicyPage]
}

public struct PolicyPage: Hashable {
    let navigationTitle: String
    let post: Post
}

public enum CommentStatus: String, Codable {
    case open
    case closed
}

public struct Post: Hashable {
    public struct Event: Hashable {
        public let date: Date
        public let timeStart: String?
        public let timeEnd: String?
        public let location: String?
    }
    public let id: Int
    public let date: Date?
    public let dateGMT: Date?
    public let modified: Date?
    public let modifiedGMT: Date?
    public let slug: String
    public let type: String
    public let link: URL?
    public let title: Rendered
    public let content: Rendered
    public let excerpt: Rendered
    public let author: [Author]
    public let commentStatus: CommentStatus
    public let topics: [TopicRef]
    public let tags: [Tag]
    public let primaryTopic: Topic?
    public let commentCount: Int
    public let thumbnail: Thumbnail
    public let events: [Event]
    public let latestComments: [Comment]
    public let allComments: [Comment]?
    public let banners: [Banner]?
    public var webAssets: [WebAsset] = []
    public var relatedPosts: [Post] = []
}

public struct PostCollection: Codable {
    let posts: [Post]
    let banners: [Banner]
}

public enum Collection {
    case latest
    case trending
    case conversation
    case topic(topicId: Int)
    case postIds(postIds: [Int])
}

public enum TopicCollection: String {
    case primary
    case searchFeature = "search"
}

public struct AuthResponse: Equatable {
    enum DeleteStatus: String, Codable, Equatable {
        case notRequested = "not-requested"
        case pendingConfirmation = "pending-confirmation"
        case pendingDelete = "pending-delete"
    }
    let id: Int
    let name: String
    let avatar: URL?
    let link: String
    let email: String
    let token: String
    let refreshToken: String
    var deleteStatus: DeleteStatus?
}

public struct DeleteUserResponse: Equatable, Codable {
    struct User: Equatable, Codable {
        let id: Int
        // Other attributes ignored
    }
    let error: Bool
    let message: String
    let user: User?
}

public struct Comments: Codable, Hashable {
    let comments: [Comment]
    let posts: [PostSummary]
}

public struct Comment: Hashable, Equatable {
    enum Source: String, Codable {
        case wordpress
        case facebook
    }
    let source: Source
    let id: Int
    let name: String
    let avatar: URL?
    let date: Date
    let dateGMT: Date?
    let link: URL?
    let content: String
    let excerpt: String
    let post: String?
    let children: [Comment]
}

public struct CommentResponse: Codable {
    let id: Int
    let post: Int
    let parent: Int
    let author: Int
}

public struct Reply: Hashable, Equatable, Codable {
    let content: String
    let post: Int
    let parent: Int?
}

public struct PostSummary: Hashable, Equatable {
    let id: Int
    let date: Date?
    let dateGMT: Date?
    let slug: String
    let type: String
    let link: URL?
    let title: String
    let author: [Author]
    let commentCount: Int
    let commentStatus: CommentStatus
    let latestCommentDate: Date?
    let primaryTopic: Topic?
}

public enum NotificationType: Hashable, Equatable {
    case replyToComments
    case topic(topicSlug: String)
    
    var requiresLogin: Bool {
        switch self {
        case .replyToComments:
            return true
        default:
            return false
        }
    }
    
    var title: String {
        switch self {
        case .replyToComments:
            return "Replies to Comments"
        case .topic(let topicSlug):
            return topicSlug
        }
    }
}

public struct EventCalendar: Hashable, Equatable {
    public struct TimeSlot: Hashable, Equatable {
        var time: Date
        var postIds: [String]
    }
    
    let schedule: [TimeSlot]
    let posts: [Post]
}

public struct Feedback: Codable {
    var email: String?
    var message: String
    var version: String
}
