//
//  PinnedTimeline.swift
//  Tusker
//
//  Created by Shadowfacts on 1/27/23.
//  Copyright © 2023 Shadowfacts. All rights reserved.
//

import UIKit
import Pachyderm

enum PinnedTimeline: Codable, Equatable, Hashable {
    case home
    case `public`(local: Bool)
    case tag(hashtag: String)
    case list(id: String)
    case instance(URL)
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        let type = try container.decode(String.self, forKey: .type)
        switch type {
        case "home":
            self = .home
        case "public":
            self = .public(local: try container.decode(Bool.self, forKey: .local))
        case "tag":
            self = .tag(hashtag: try container.decode(String.self, forKey: .hashtag))
        case "list":
            self = .list(id: try container.decode(String.self, forKey: .listID))
        case "instance":
            self = .instance(try container.decode(URL.self, forKey: .instanceURL))
        default:
            throw DecodingError.dataCorruptedError(forKey: CodingKeys.type, in: container, debugDescription: "PinnedTimeline type must be one of 'home', 'local', 'tag', 'list', or 'instance'")
        }
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        switch self {
        case .home:
            try container.encode("home", forKey: .type)
        case .public(let local):
            try container.encode("public", forKey: .type)
            try container.encode(local, forKey: .local)
        case .tag(let hashtag):
            try container.encode("tag", forKey: .type)
            try container.encode(hashtag, forKey: .hashtag)
        case .list(let id):
            try container.encode("list", forKey: .type)
            try container.encode(id, forKey: .listID)
        case .instance(let url):
            try container.encode("instance", forKey: .type)
            try container.encode(url, forKey: .instanceURL)
        }
    }
    
    init?(timeline: Timeline) {
        switch timeline {
        case .home:
            self = .home
        case .public(let local):
            self = .public(local: local)
        case .tag(let hashtag):
            self = .tag(hashtag: hashtag)
        case .list(let id):
            self = .list(id: id)
        case .direct:
            return nil
        }
    }
    
    var timeline: Timeline? {
        switch self {
        case .home:
            return .home
        case .public(let local):
            return .public(local: local)
        case .tag(let hashtag):
            return .tag(hashtag: hashtag)
        case .list(let id):
            return .list(id: id)
        case .instance(_):
            return nil
        }
    }
    
    var title: String {
        switch self {
        case .home:
            return "Home"
        case let .public(local):
            return local ? "Local" : "Federated"
        case let .tag(hashtag):
            return "#\(hashtag)"
        case .list:
            return "List"
        case .instance(let url):
            return url.host!
        }
    }
    
    var image: UIImage {
        switch self {
        case .home:
            return UIImage(systemName: "house.fill")!
        case let .public(local):
            if local {
                return UIImage(systemName: "person.and.person.fill")!
            } else {
                return UIImage(systemName: "globe")!
            }
        case .list(id: _):
            return UIImage(systemName: "list.bullet")!
        case .tag(hashtag: _):
            return UIImage(systemName: "number")!
        case .instance(_):
            return UIImage(systemName: "globe")!
        }
    }
    
    private enum CodingKeys: String, CodingKey {
        case type
        case local
        case hashtag
        case listID
        case instanceURL
    }
}
