//
//  List.swift
//  Pachyderm
//
//  Created by Shadowfacts on 9/9/18.
//  Copyright © 2018 Shadowfacts. All rights reserved.
//

import Foundation

public struct List: ListProtocol, Decodable, Equatable, Hashable, Sendable {
    public let id: String
    public let title: String
    public let replyPolicy: ReplyPolicy?
    public let exclusive: Bool?
    
    public var timeline: Timeline {
        return .list(id: id)
    }
    
    public init(id: String, title: String, replyPolicy: ReplyPolicy?, exclusive: Bool?) {
        self.id = id
        self.title = title
        self.replyPolicy = replyPolicy
        self.exclusive = exclusive
    }
    
    public static func ==(lhs: List, rhs: List) -> Bool {
        return lhs.id == rhs.id && lhs.title == rhs.title
    }
    
    public func hash(into hasher: inout Hasher) {
        hasher.combine(id)
        hasher.combine(title)
    }
    
    public static func getAccounts(_ listID: String, range: RequestRange = .default) -> Request<[Account]> {
        var request = Request<[Account]>(method: .get, path: "/api/v1/lists/\(listID)/accounts")
        request.range = range
        return request
    }
    
    public static func update(_ listID: String, title: String, replyPolicy: ReplyPolicy?, exclusive: Bool?) -> Request<List> {
        var params = ["title" => title]
        if let replyPolicy {
            params.append("replies_policy" => replyPolicy.rawValue)
        }
        if let exclusive {
            params.append("exclusive" => exclusive)
        }
        return Request<List>(method: .put, path: "/api/v1/lists/\(listID)", body: ParametersBody(params))
    }
    
    public static func delete(_ listID: String) -> Request<Empty> {
        return Request<Empty>(method: .delete, path: "/api/v1/lists/\(listID)")
    }
    
    public static func add(_ listID: String, accounts accountIDs: [String]) -> Request<Empty> {
        return Request<Empty>(method: .post, path: "/api/v1/lists/\(listID)/accounts", body: ParametersBody(
                "account_ids" => accountIDs
            ))
    }
    
    public static func remove(_ listID: String, accounts accountIDs: [String]) -> Request<Empty> {
        return Request<Empty>(method: .delete, path: "/api/v1/lists/\(listID)/accounts", body: ParametersBody(
                "account_ids" => accountIDs
            ))
    }
    
    private enum CodingKeys: String, CodingKey {
        case id
        case title
        case replyPolicy = "replies_policy"
        case exclusive
    }
}

extension List {
    public enum ReplyPolicy: String, Codable, Hashable, CaseIterable, Sendable {
        case followed, list, none
    }
}
