package parser

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

find_script_block :: proc(
	str: string,
) -> (
	start_idx, end_idx: int,
	is_block: bool,
	block_type: string,
	content: string,
) {
	for i := 0; i < len(str); i += 1 {
		if str[i] == '$' && i + 1 < len(str) && str[i + 1] == '[' {
			if end, inner, ok := match_single(str[i + 1:], '[', ']'); ok {
				inner = strings.trim_space(inner)
				if strings.has_prefix(inner, "/") {
					continue
				}
				if inner == "script" || inner == "js" || inner == "javascript" {
					b := strings.builder_make(context.temp_allocator)
					strings.write_string(&b, "$[/")
					strings.write_string(&b, inner)
					strings.write_string(&b, "]")
					close_tag := strings.to_string(b)
					close_idx := strings.index(str[i + 1 + end:], close_tag)
					if close_idx != -1 {
						close_idx += i + 1 + end
						content := str[i + 1 + end:close_idx]
						return i, close_idx + len(
							close_tag,
						), true, inner, strings.trim_space(content)
					}
				}
			}
		}
	}
	return -1, -1, false, "", ""
}

find_embed :: proc(
	str: string,
) -> (
	start_idx, end_idx: int,
	is_embed: bool,
	url: string,
	alt: string,
	embed_type: string,
) {
	for i := 0; i < len(str); i += 1 {
		if str[i] == '$' && i + 1 < len(str) {
			if str[i + 1] == '[' {
				if end, alt_text, url_text, ok := match_pair(str[i + 1:], '[', ']', '(', ')'); ok {
					clean_url := url_text
					type_hint := ""
					if pipe_idx := strings.index_byte(url_text, '|'); pipe_idx != -1 {
						clean_url = url_text[:pipe_idx]
						type_hint = url_text[pipe_idx + 1:]
					}

					if mime.is_url(clean_url) {
						e_type := ""
						if type_hint != "" {
							e_type = mime.parse_type_hint(type_hint)
						}
						if e_type == "" {
							e_type = mime.detect_embed_type(clean_url)
						}
						return i, i + 1 + end, true, clean_url, alt_text, e_type
					}
				}
				if end, inner, ok := match_single(str[i + 1:], '[', ']'); ok {
					url_text := inner
					type_hint := ""
					if pipe_idx := strings.index_byte(inner, '|'); pipe_idx != -1 {
						url_text = inner[:pipe_idx]
						type_hint = inner[pipe_idx + 1:]
					}

					if mime.is_url(url_text) {
						e_type := ""
						if type_hint != "" {
							e_type = mime.parse_type_hint(type_hint)
						}
						if e_type == "" {
							e_type = mime.detect_embed_type(url_text)
						}
						return i, i + 1 + end, true, url_text, url_text, e_type
					}
				}
			} else if str[i + 1] == '(' {
				if end, url_text, alt_text, ok := match_pair(str[i + 1:], '(', ')', '[', ']'); ok {
					clean_url := url_text
					type_hint := ""
					if pipe_idx := strings.index_byte(url_text, '|'); pipe_idx != -1 {
						clean_url = url_text[:pipe_idx]
						type_hint = url_text[pipe_idx + 1:]
					}

					if mime.is_url(clean_url) {
						e_type := ""
						if type_hint != "" {
							e_type = mime.parse_type_hint(type_hint)
						}
						if e_type == "" {
							e_type = mime.detect_embed_type(clean_url)
						}
						return i, i + 1 + end, true, clean_url, alt_text, e_type
					}
				}
				if end, inner, ok := match_single(str[i + 1:], '(', ')'); ok {
					url_text := inner
					type_hint := ""
					if pipe_idx := strings.index_byte(inner, '|'); pipe_idx != -1 {
						url_text = inner[:pipe_idx]
						type_hint = inner[pipe_idx + 1:]
					}

					if mime.is_url(url_text) {
						e_type := ""
						if type_hint != "" {
							e_type = mime.parse_type_hint(type_hint)
						}
						if e_type == "" {
							e_type = mime.detect_embed_type(url_text)
						}
						return i, i + 1 + end, true, url_text, url_text, e_type
					}
				}
			}
		}
	}

	return -1, -1, false, "", "", ""
}

parse_embeds :: proc(tok: ^token.Token) {
	if tok.type == .CodeBlock || tok.type == .InlineCode {
		return
	}
	if tok.children != nil {
		for i := 0; i < len(tok.children); i += 1 {
			parse_embeds(tok.children[i])
		}
	}

	if tok.type == .Text {
		str, ok := tok.value.(string)
		if !ok {
			return
		}

		s_start, s_end, is_script, s_type, s_content := find_script_block(str)
		if is_script {
			tok.value = nil

			if s_start > 0 {
				push_token(tok, .Text, str[:s_start])
			}

			script_token := push_token(tok, .ScriptBlock, s_content)

			if s_end < len(str) {
				rem := push_token(tok, .Text, str[s_end:])
				parse_embeds(rem)
			}
			return
		}

		start_idx, end_idx, is_embed, url, alt, e_type := find_embed(str)
		if !is_embed {
			return
		}

		tok.value = nil

		if start_idx > 0 {
			push_token(tok, .Text, str[:start_idx])
		}

		embed_token_type: token.TokenType
		if e_type == "image" {
			embed_token_type = .Image
		} else if e_type == "audio" {
			embed_token_type = .Audio
		} else if e_type == "video" {
			embed_token_type = .Video
		} else if e_type == "script" {
			embed_token_type = .Script
		} else {
			embed_token_type = .Iframe
		}

		embed_token := push_token(tok, embed_token_type, url)
		push_token(embed_token, .Text, alt)

		if end_idx < len(str) {
			rem := push_token(tok, .Text, str[end_idx:])
			parse_embeds(rem)
		}
	}
}
