import AppKit
import Foundation
import Version
import Path
import XcodesKit

public struct XcodeID: Codable, Hashable, Identifiable {
    public let version: Version
    public let architectures: [Architecture]?
    
    public var id: String {
        let architectures = architectures?.map { $0.rawValue}.joined() ?? ""
        return version.description + architectures
    }
    
    public init(version: Version, architectures: [Architecture]? = nil) {
        self.version = version
        self.architectures = architectures
    }
}

struct Xcode: Identifiable, CustomStringConvertible {
    var version: Version {
        return id.version
    }
    /// Other Xcode versions that have the same build identifier
    let identicalBuilds: [XcodeID]
    var installState: XcodeInstallState
    let selected: Bool
    let icon: NSImage?
    let requiredMacOSVersion: String?
    let releaseNotesURL: URL?
    let releaseDate: Date?
    let sdks: SDKs?
    let compilers: Compilers?
    let downloadFileSize: Int64?
    let architectures: [Architecture]?
    let id: XcodeID
    
    init(
        version: Version,
        identicalBuilds: [XcodeID] = [],
        installState: XcodeInstallState,
        selected: Bool,
        icon: NSImage?,
        requiredMacOSVersion: String? = nil,
        releaseNotesURL: URL? = nil,
        releaseDate: Date? = nil,
        sdks: SDKs? = nil,
        compilers: Compilers? = nil,
        downloadFileSize: Int64? = nil,
        architectures: [Architecture]? = nil
    ) {
        self.identicalBuilds = identicalBuilds
        self.installState = installState
        self.selected = selected
        self.icon = icon
        self.requiredMacOSVersion = requiredMacOSVersion
        self.releaseNotesURL = releaseNotesURL
        self.releaseDate = releaseDate
        self.sdks = sdks
        self.compilers = compilers
        self.downloadFileSize = downloadFileSize
        self.architectures = architectures
        self.id = XcodeID(version: version, architectures: architectures)
    }
    
    var description: String {
        version.appleDescription
    }
    
    var downloadFileSizeString: String? {
        if let downloadFileSize = downloadFileSize {
            return ByteCountFormatter.string(fromByteCount: downloadFileSize, countStyle: .file)
        } else {
            return nil
        }
    }
    
    var installedPath: Path? {
        switch installState {
            case .installed(let path):
                return path
            default:
                return nil
        }
    }
    
}
