package renderer

import "../mime"
import "../token"
import "core:fmt"
import "core:strings"

render_aligned_cell :: proc(tok: ^token.Token, tag: string) {
	align := get_alignment_attribute(tok)
	if align != "" {
		fmt.printf("<%s align=\"%s\">", tag, align)
		for child in tok.children[0].children {
			print_html(child)
		}
	} else {
		fmt.printf("<%s>", tag)
		for child in tok.children {
			print_html(child)
		}
	}
	fmt.printf("</%s>", tag)
}

render_simple_wrapper :: proc(tok: ^token.Token, tag: string) {
	fmt.printf("<%s>", tag)
	for child in tok.children {
		print_html(child)
	}
	fmt.printf("</%s>", tag)
}

render_div_wrapper :: proc(tok: ^token.Token, align: string) {
	fmt.printf("<div align=\"%s\">", align)
	for child in tok.children {
		print_html(child)
	}
	fmt.print("</div>")
}

render_container :: proc(tok: ^token.Token, tag: string) {
	fmt.printf("<%s>\n", tag)
	for child in tok.children {
		print_html(child)
	}
	fmt.printf("</%s>\n", tag)
}

render_media_object :: proc(tok: ^token.Token, mime_type: string) {
	url, ok := tok.value.(string)
	if !ok {
		return
	}
	b := strings.builder_make(context.temp_allocator)
	for child in tok.children {
		get_text_content(child, &b)
	}
	alt_text := strings.to_string(b)
	if alt_text == "" {
		alt_text = url
	}
	fmt.printf("<object data=\"%s\" type=\"%s\">\n", escape_html(url), escape_html(mime_type))
	fmt.printf("<param name=\"src\" value=\"%s\">\n", escape_html(url))
	fmt.printf("<param name=\"autoplay\" value=\"false\">\n")
	fmt.printf("<param name=\"controller\" value=\"true\">\n")
	fmt.printf("<a href=\"%s\">%s</a>\n", escape_html(url), escape_html(alt_text))
	fmt.print("</object>\n")
}

print_html :: proc(tok: ^token.Token) {
	switch tok.type {
	case token.TokenType.Root:
		has_footnotes := false
		for child in tok.children {
			if child.type == .FootnoteDef && !has_footnotes {
				fmt.print("<hr class=\"footnotes-sep\">\n")
				has_footnotes = true
			}
			print_html(child)
		}

	case token.TokenType.Header:
		level := 1
		if v, ok := tok.value.(int); ok {
			level = v
		}

		b := strings.builder_make(context.temp_allocator)
		for child in tok.children {
			get_text_content(child, &b)
		}
		slug := slugifyifyifyify(strings.to_string(b))

		fmt.printf("<h%d id=\"%s\">", level, escape_html(slug))
		for child in tok.children {
			print_html(child)
		}
		fmt.printf("</h%d>\n", level)

	case token.TokenType.Paragraph:
		only_var_defs := check_only_var_defs(tok)
		if !only_var_defs {
			fmt.print("<p>")
			for child in tok.children {
				print_html(child)
			}
			fmt.print("</p>\n")
		} else {
			for child in tok.children {
				if child.type != .BreakLine {
					print_html(child)
				}
			}
		}

	case token.TokenType.Blockquote:
		render_container(tok, "blockquote")

	case token.TokenType.UnorderedList:
		render_container(tok, "ul")

	case token.TokenType.OrderedList:
		render_container(tok, "ol")

	case token.TokenType.ListItem:
		fmt.print("<li>")
		for child in tok.children {
			print_html(child)
		}
		fmt.print("</li>\n")

	case token.TokenType.Bold:
		render_simple_wrapper(tok, "strong")

	case token.TokenType.Italics:
		render_simple_wrapper(tok, "em")

	case token.TokenType.Strikethrough:
		render_simple_wrapper(tok, "strike")

	case token.TokenType.Table:
		render_container(tok, "table")

	case token.TokenType.TableHeaderRow:
		fmt.print("<tr>")
		for child in tok.children {
			render_aligned_cell(child, "th")
		}
		fmt.print("</tr>\n")

	case token.TokenType.TableRow:
		fmt.print("<tr>")
		for child in tok.children {
			print_html(child)
		}
		fmt.print("</tr>\n")

	case token.TokenType.TableCell:
		render_aligned_cell(tok, "td")

	case token.TokenType.TableSeparator:
		fmt.print("<tr class=\"table-sep\"><td colspan=\"100\"></td></tr>\n")

	case token.TokenType.Left:
		render_div_wrapper(tok, "left")

	case token.TokenType.Right:
		render_div_wrapper(tok, "right")

	case token.TokenType.Middle:
		render_div_wrapper(tok, "center")

	case token.TokenType.FootnoteRef:
		if id, ok := tok.value.(string); ok {
			fmt.printf(
				"<a href=\"#fn-%s\" id=\"ref-%s\"><sup>%s</sup></a>",
				escape_html(id),
				escape_html(id),
				escape_html(id),
			)
		}

	case token.TokenType.FootnoteDef:
		if id, ok := tok.value.(string); ok {
			fmt.printf(
				"<div class=\"footnote\" id=\"fn-%s\"><a href=\"#ref-%s\">^</a> ",
				escape_html(id),
				escape_html(id),
			)
			for child in tok.children {
				print_html(child)
			}
			fmt.print("</div>\n")
		}

	case token.TokenType.CodeBlock:
		lang := ""
		if v, ok := tok.value.(string); ok && v != "" {
			lang = v
		}
		if lang != "" {
			fmt.printf("<pre><code class=\"lang-%s\">", lang)
		} else {
			fmt.print("<pre><code>")
		}
		for i := 0; i < len(tok.children); i += 1 {
			print_html(tok.children[i])
			if i + 1 < len(tok.children) {
				fmt.print("\n")
			}
		}
		fmt.print("\n</code></pre>\n")

	case token.TokenType.InlineCode:
		if code, ok := tok.value.(string); ok {
			fmt.printf("<code>%s</code>", escape_html(code))
		}

	case token.TokenType.HorizontalRule:
		fmt.print("<hr>\n")

	case token.TokenType.Underline:
		fmt.print("<u>")
		for child in tok.children {
			print_html(child)
		}
		fmt.print("</u>")

	case token.TokenType.Superscript:
		fmt.print("<sup>")
		for child in tok.children {
			print_html(child)
		}
		fmt.print("</sup>")

	case token.TokenType.Subscript:
		fmt.print("<sub>")
		for child in tok.children {
			print_html(child)
		}
		fmt.print("</sub>")

	case token.TokenType.HeaderLink:
		if target, ok := tok.value.(string); ok {
			slug := slugifyifyifyify(target)
			fmt.printf("<a href=\"#%s\">", escape_html(slug))
			for child in tok.children {
				print_html(child)
			}
			fmt.print("</a>")
		}

	case token.TokenType.Link:
		if url, ok := tok.value.(string); ok {
			fmt.printf("<a href=\"%s\">", escape_html(url))
			for child in tok.children {
				print_html(child)
			}
			fmt.print("</a>")
		}

	case token.TokenType.Image:
		if url, ok := tok.value.(string); ok {
			b := strings.builder_make(context.temp_allocator)
			for child in tok.children {
				get_text_content(child, &b)
			}
			alt_text := strings.to_string(b)
			fmt.printf("<img src=\"%s\" alt=\"%s\">", escape_html(url), escape_html(alt_text))
		}

	case token.TokenType.Audio:
		if url, ok := tok.value.(string); ok {
			render_media_object(tok, mime.detect_mime_type(url))
		}

	case token.TokenType.Video:
		if url, ok := tok.value.(string); ok {
			render_media_object(tok, mime.detect_mime_type(url))
		}

	case token.TokenType.Iframe:
		if url, ok := tok.value.(string); ok {
			fmt.printf("<iframe src=\"%s\"></iframe>", escape_html(url))
		}

	case token.TokenType.Script:
		if url, ok := tok.value.(string); ok {
			fmt.printf("<script src=\"%s\"></script>", escape_html(url))
		}

	case token.TokenType.ScriptBlock:
		if content, ok := tok.value.(string); ok {
			fmt.printf("<script>%s</script>", content)
		}

	case token.TokenType.Variable:
		if name, ok := tok.value.(string); ok {
			fmt.printf("<span data-tlm-var=\"%s\">", escape_html(name))
			for child in tok.children {
				print_html(child)
			}
			fmt.print("</span>")
		}

	case token.TokenType.VariableDef:
		if name, ok := tok.value.(string); ok {
			b := strings.builder_make(context.temp_allocator)
			for child in tok.children {
				get_text_content(child, &b)
			}
			val := strings.to_string(b)
			fmt.printf(
				"<template data-tlm-def=\"%s\" data-tlm-value=\"%s\"></template>",
				escape_html(name),
				escape_html(val),
			)
		}

	case token.TokenType.BreakLine:
		fmt.print("<br>\n")

	case token.TokenType.Text:
		if v, ok := tok.value.(string); ok {
			fmt.print(escape_html(v))
		}
		for child in tok.children {
			print_html(child)
		}
	}
}
