
enum KnownHeaderElement {

    case codeHightlighting

    case modelViewer

    /// CSS File to style the audio player
    case audioPlayerCss

    /// JavaScript file for the audio player
    case audioPlayerJs

    case imageCompareJs

    case imageCompareCss

    case swiperCss

    case swiperJs

    /// The Javascript to compute and animate route statistics
    case routeJs

    case style(String)

    func header(content: Content) -> HeaderElement? {
        switch self {
        case .codeHightlighting:
            if let file = content.settings.pages.codeHighlightingJsFile {
                return HeaderElement.js(file: file, defer: true)
            }
        case .modelViewer:
            if let file = content.settings.pages.modelViewerJsFile {
                return HeaderElement.jsModule(file)
            }
        case .audioPlayerCss:
            if let file = content.settings.audioPlayer.audioPlayerCssFile {
                return .css(file: file, order: HeaderElement.audioPlayerCssOrder)
            }
        case .audioPlayerJs:
            if let file = content.settings.audioPlayer.audioPlayerJsFile {
                return .js(file: file, defer: true)
            }
        case .imageCompareJs:
            if let file = content.settings.pages.imageCompareJsFile {
                return .js(file: file, defer: true)
            }
        case .imageCompareCss:
            if let file = content.settings.pages.imageCompareCssFile {
                return .css(file: file, order: HeaderElement.imageCompareCssOrder)
            }
        case .swiperCss:
            if let swiperCss = content.settings.posts.swiperCssFile {
                return .css(file: swiperCss, order: HeaderElement.swiperCssFileOrder)
            }
        case .swiperJs:
            if let swiperJs = content.settings.posts.swiperJsFile {
                return .js(file: swiperJs, defer: true)
            }
        case .routeJs:
            if let routeJs = content.settings.pages.routeJsFile {
                return .js(file: routeJs, defer: false)
            }
        case .style(let code):
            return .style(code)
        }
        return nil
    }
}

extension KnownHeaderElement: Equatable {

    static func == (lhs: KnownHeaderElement, rhs: KnownHeaderElement) -> Bool {
        lhs.description == rhs.description
    }
}

extension KnownHeaderElement: Hashable {

    func hash(into hasher: inout Hasher) {
        hasher.combine(description)
    }
}

extension KnownHeaderElement: CustomStringConvertible {

    var description: String {
        switch self {
        case .codeHightlighting:
            return "code-highlighting"
        case .modelViewer:
            return "model-viewer"
        case .audioPlayerCss:
            return "audio-player-css"
        case .audioPlayerJs:
            return "audio-player-js"
        case .imageCompareJs:
            return "image-compare-js"
        case .imageCompareCss:
            return "image-compare-css"
        case .swiperCss:
            return "swiper-css"
        case .swiperJs:
            return "swiper-js"
        case .routeJs:
            return "route-js"
        case .style(let style):
            return "style: " + style
        }
    }
}
