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

import Foundation
import WebURL
import WebURLFoundationExtras

public struct Hashtag: Codable, Sendable {
    public let name: String
    public let url: WebURL
    /// Only present when returned from the trending hashtags endpoint
    public let history: [History]?
    /// Only present on Mastodon >= 4 and when logged in
    public let following: Bool?
    
    public init(name: String, url: URL) {
        self.name = name
        self.url = WebURL(url)!
        self.history = nil
        self.following = nil
    }
    
    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.name = try container.decode(String.self, forKey: .name)
        // pixelfed (possibly others) don't fully escape special characters in the hashtag url
        self.url = try container.decode(WebURL.self, forKey: .url)
        self.history = try container.decodeIfPresent([History].self, forKey: .history)
        self.following = try container.decodeIfPresent(Bool.self, forKey: .following)
    }
    
    public func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(name, forKey: .name)
        try container.encode(url, forKey: .url)
        try container.encodeIfPresent(history, forKey: .history)
        try container.encodeIfPresent(following, forKey: .following)
    }
    
    public static func follow(name: String) -> Request<Hashtag> {
        return Request(method: .post, path: "/api/v1/tags/\(name)/follow")
    }
    
    public static func unfollow(name: String) -> Request<Hashtag> {
        return Request(method: .post, path: "/api/v1/tags/\(name)/unfollow")
    }
    
    private enum CodingKeys: String, CodingKey {
        case name
        case url
        case history
        case following
    }
}

extension Hashtag: Equatable, Hashable {
    public static func ==(lhs: Hashtag, rhs: Hashtag) -> Bool {
        return lhs.name == rhs.name
    }
    
    public func hash(into hasher: inout Hasher) {
        hasher.combine(name)
    }
}
