import Ink

struct MarkdownCodeProcessor: MarkdownProcessor {

    static let modifier: Modifier.Target = .codeBlocks

    private let results: PageGenerationResults

    private let blocks: [ContentBlock : BlockProcessor]

    private let other: OtherCodeBlock

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

        self.blocks = ContentBlock.allCases.reduce(into: [:]) { blocks, block in
            blocks[block] = block.processor.init(content: content, results: results, language: language)
        }
    }

    private let codeHighlightFooter = "<script>hljs.highlightAll();</script>"

    func process(html: String, markdown: Substring) -> String {
        let input = String(markdown)
        let rawBlockId = input.dropAfterFirst("\n").dropBeforeFirst("```").trimmed.lowercased()
        guard let blockId = ContentBlock(rawValue: rawBlockId) else {
            guard knownCodeBlocks.contains(rawBlockId) else {
                results.invalid(block: nil, markdown)
                return ""
            }
            return other.process(html: html)
        }
        return blocks[blockId]!.process(markdown)
    }

    private let knownCodeBlocks: Set<String> = [
        "bash", "nginx", "json", "css", "html", "markdown", ""
    ]
}
