
struct WorkoutBlock: KeyedBlockProcessor {

    enum Key: String {
        case chartTitle
        case components
        case mapTitle
        case caption
        case file
    }

    static let blockId: ContentBlock = .route

    let content: Content

    let results: PageGenerationResults

    let language: ContentLanguage

    init(content: Content, results: PageGenerationResults, language: ContentLanguage) {
        self.content = content
        self.results = results
        self.language = language
    }

    private var thumbnailWidth: Int {
        content.settings.pages.contentWidth
    }

    private var largeImageWidth: Int {
        content.settings.pages.largeImageWidth
    }

    func process(_ arguments: [Key : String], markdown: Substring) -> String {
        guard let fileId = arguments[.file] else {
            invalid(markdown)
            return ""
        }

        let rawComponents = arguments[.components]
        var displayedTypes: Set<RouteStatisticType> = []
        if let rawComponents {
            rawComponents.components(separatedBy: ",").compactMap { $0.trimmed.nonEmpty }.forEach { rawType in
                if let type = RouteStatisticType(rawValue: rawType) {
                    displayedTypes.insert(type)
                } else {
                    results.warning("Unknown component type '\(rawType)' in route block")
                }
            }
        }
        if displayedTypes.isEmpty {
            displayedTypes = Set(RouteStatisticType.allCases)
        }

        guard let file = content.file(fileId) else {
            results.missing(file: fileId, source: "Route block")
            return ""
        }
        results.used(file: file)

        // Note: Use png type, otherwise the original type would be .route
        let thumbnail = file.imageSet(type: .png, width: thumbnailWidth, height: thumbnailWidth, language: language)
        results.require(imageSet: thumbnail)

        let largeImage = file.imageSet(type: .png, width: largeImageWidth, height: largeImageWidth, language: language)
        results.require(imageSet: largeImage)
        
        results.require(header: .routeJs)

        let id = fileId.replacingOccurrences(of: ".", with: "-")

        let views = RouteViews(
            localization: language == .english ? .english : .german,
            chartTitle: arguments[.chartTitle],
            chartId: "chart-" + id,
            displayedTypes: displayedTypes,
            mapTitle: arguments[.mapTitle],
            mapId: "map-" + id,
            filePath: file.absoluteUrl,
            imageId: "image-" + id,
            thumbnail: thumbnail,
            largeImage: largeImage,
            caption: arguments[.caption])

        results.require(footer: views.script)
        results.require(icons: displayedTypes.map { $0.icon })

        return views.content
    }
}
