import Foundation

/**
 A version of an image with a specific size and possible different image type.
 */
struct ImageVersion {

    /// The name of the image file to convert
    let image: FileResource

    let type: FileType

    let maximumWidth: Int

    let maximumHeight: Int

    let quality: CGFloat

    init(image: FileResource, type: FileType, maximumWidth: CGFloat, maximumHeight: CGFloat, quality: CGFloat = 0.7) {
        self.image = image
        self.type = type
        self.maximumWidth = Int(maximumWidth)
        self.maximumHeight = Int(maximumHeight)
        self.quality = quality
    }

    init(image: FileResource, type: FileType, maximumWidth: Int, maximumHeight: Int, quality: CGFloat = 0.7) {
        self.image = image
        self.type = type
        self.maximumWidth = maximumWidth
        self.maximumHeight = maximumHeight
        self.quality = quality
    }

    /// A unique id of the version for this image (not unique across images)
    var versionId: String {
        "\(maximumWidth)-\(maximumHeight)-\(type.fileExtension!)"
    }

    /// The path of the generated image version in the output folder (including leading slash)
    var outputPath: String {
        image.outputPath(width: maximumWidth, height: maximumHeight, type: type)
    }

    var wasPreviouslyGenerated: Bool {
        image.generatedImageVersions.contains(versionId)
    }

    func wasNowGenerated() {
        DispatchQueue.main.async {
            image.generatedImageVersions.insert(versionId)
        }
    }
}

extension ImageVersion: Identifiable {

    var id: String {
        image.identifier + "-" + versionId
    }
}

extension ImageVersion: Equatable {

    static func == (lhs: ImageVersion, rhs: ImageVersion) -> Bool {
        lhs.image.identifier == rhs.image.identifier &&
        lhs.maximumWidth == rhs.maximumWidth &&
        lhs.maximumHeight == rhs.maximumHeight &&
        lhs.type == rhs.type
    }
}

extension ImageVersion: Hashable {

    func hash(into hasher: inout Hasher) {
        hasher.combine(image.identifier)
        hasher.combine(maximumWidth)
        hasher.combine(maximumHeight)
        hasher.combine(type)
    }
}

extension ImageVersion: Comparable {

    static func < (lhs: ImageVersion, rhs: ImageVersion) -> Bool {
        lhs.id < rhs.id
    }
}
