import Foundation
import Ink

struct PostContentGenerator {

    private let content: Content

    private let results: PageGenerationResults

    private let language: ContentLanguage

    private let post: Post

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

    func generate() -> String {
        let parser = MarkdownParser(modifiers: [
            Modifier(target: .images, closure: handleImage),
            Modifier(target: .codeBlocks, closure: handleCode),
            Modifier(target: .links, closure: handleLink)
        ])
        return parser.html(from: post.localized(in: language).text)
    }

    private func handleImage(
        html: String,
        markdown: Substring
    ) -> String {
        results.warning("Image in \(postDescription)")
        return ""
    }

    private func handleCode(
        html: String,
        markdown: Substring
    ) -> String {
        results.warning("Code in \(postDescription)")
        return ""
    }

    private var postDescription: String {
        "content of post \(post.identifier) (\(language.shortText))"
    }

    private func handleLink(
        html: String,
        markdown: Substring
    ) -> String {
        let converter = MarkdownLinkProcessor(content: content, results: self, language: language)
        let markdownUrl = markdown.between("(", and: ")")
        let text = markdown.between("[", and: "]")
        let url = converter.convert(markdownUrl: markdownUrl)?.url ?? markdownUrl
        return "<span class='link' onclick=\"location.href='\(url)'; event.stopPropagation();\">\(text)</span>"
    }
}

extension PostContentGenerator: ItemLinkResults {

    func externalLink(to url: String) {
        results.externalLink(to: url)
    }
    
    func missing(page: String, source: String) {
        results.missing(page: page, source: postDescription)
    }
    
    func linked(to page: Page) {
        results.linked(to: page)
    }
    
    func missing(tag: String, source: String) {
        results.missing(tag: tag, source: postDescription)
    }
    
    func linked(to tag: Tag) {
        results.linked(to: tag)
    }
    
    func missing(file: String, source: String) {
        results.missing(file: file, source: postDescription)
    }
    
    func require(file: FileResource) {
        results.require(file: file)
    }
}
