//
//  Server.swift
//  iKeyMon
//
//  Created by tracer on 30.03.25.
//

import Foundation

struct Server: Identifiable, Codable, Hashable, Equatable {
    let id: UUID
    var hostname: String
    var groupID: UUID?
    var info: ServerInfo?
    var pingable: Bool

    init(id: UUID = UUID(), hostname: String, groupID: UUID? = nil, info: ServerInfo? = nil, pingable: Bool = false) {
        self.id = id
        self.hostname = hostname
        self.groupID = groupID
        self.info = info
        self.pingable = pingable
    }

    // MARK: - Manual conformance

    static func == (lhs: Server, rhs: Server) -> Bool {
        lhs.id == rhs.id && lhs.hostname == rhs.hostname && lhs.groupID == rhs.groupID && lhs.info == rhs.info && lhs.pingable == rhs.pingable
    }

    func hash(into hasher: inout Hasher) {
        hasher.combine(id)
        hasher.combine(hostname)
        hasher.combine(groupID)
        hasher.combine(info)
        hasher.combine(pingable)
    }

    enum CodingKeys: String, CodingKey {
        case id, hostname, groupID, info, pingable
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        id = try container.decode(UUID.self, forKey: .id)
        hostname = try container.decode(String.self, forKey: .hostname)
        groupID = try container.decodeIfPresent(UUID.self, forKey: .groupID)
        info = try container.decodeIfPresent(ServerInfo.self, forKey: .info)
        pingable = try container.decodeIfPresent(Bool.self, forKey: .pingable) ?? false
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(id, forKey: .id)
        try container.encode(hostname, forKey: .hostname)
        try container.encodeIfPresent(groupID, forKey: .groupID)
        try container.encodeIfPresent(info, forKey: .info)
        try container.encode(pingable, forKey: .pingable)
    }
}
