from panflute import *

from whitespace import NBSP
from transform import FQuoted

# Heavily inspired by: git://git.ucw.cz/labsconf2022.git
def tex(e, indent_level: int=0, indent_str: str="\t") -> str:

	if hasattr(e, "attributes") and "only" in e.attributes and e.attributes["only"] != "tex":
		return ""

	if isinstance(e, ListContainer):
		return ''.join([tex(child, indent_level, indent_str) for child in e])

	content_foot = ""
	content_head = ""

	arguments = ""
	open = "{"
	close = "}"

	tag = e.tag.lower()

	tags = {
		Header: "h"+chr(64 + e.level) if hasattr(e, "level") else "",
	}
	if type(e) in tags:
		tag = tags[type(e)]


	not_implemented = {
		Citation: True,
		Cite: True,
		Definition: True,
		DefinitionItem: True,
		DefinitionList: True
	}
	if type(e) in not_implemented:
		return f'% FIXME: {type(e)}s not implemented \n'

	simple_string = {
		NBSP: "~",
		Space: " ",
		Null: "",
		LineBreak: f"\\\\",
		SoftBreak: f" ",
		HorizontalRule: "\\hr\n\n"
	}
	if type(e) in simple_string:
		return simple_string[type(e)]

	if isinstance(e, Str):
		return e.text.replace(" ", "~").replace(" ", "~")

	if isinstance(e, Para):
		return tex(e.content, 0, "")+"\n\n"

	if isinstance(e, FQuoted):
		if e.style == "cs":
			if e.quote_type == "SingleQuote":
				return f'‚{tex(e.content, 0, "")}‘'
			elif e.quote_type == "DoubleQuote":
				return f'„{tex(e.content, 0, "")}“'
		elif e.style == "en":
			if e.quote_type == "SingleQuote":
				return f'‘{tex(e.content, 0, "")}’'
			elif e.quote_type == "DoubleQuote":
				return f'“{tex(e.content, 0, "")}”'
		else:
			if e.quote_type == "SingleQuote":
				return f'\'{tex(e.content, 0, "")}\''
			elif e.quote_type == "DoubleQuote":
				return f'"{tex(e.content, 0, "")}"'
			else:
				return f'"{tex(e.content, 0, "")}"'

	if isinstance(e, BulletList):
		tag = "list"
		open = ""
		arguments = "{o}"
		close = "\\endlist"

	if isinstance(e, OrderedList):
		tag = "list"
		open = ""
		styles = {
			"DefaultStyle": "n",
			"Decimal": "n",
			"LowerRoman": "i",
			"UpperRoman:": "I",
			"LowerAlpha": "a",
			"UpperAlpha": "A"
		}
		style = styles[e.style]
		delimiters = {
			"DefaultDelim": f"{style}.",
			"Period": f"{style}.",
			"OneParen": f"{style})",
			"TwoParens": f"({style})"
		}
		style = delimiters[e.delimiter]
		arguments = f"{{{style}}}"
		close = "\\endlist"
		# FIXME: Starting number of list
	
	if isinstance(e, ListItem):
		tag = ":"

	if isinstance(e, Link):
		tag = "linkurl"
		arguments = f'{{{e.url}}}'

	if isinstance(e, Math):
		if e.format == "DisplayMath":
			return f'$${e.text}$$\n'
		else:
			return f'${e.text}$'

	if isinstance(e, Note):
		tag = "fn"
		if len(e.content) == 1 and isinstance(e.content[0], Para):
			return f'\\fn{{{tex(e.content[0].content, 0, "")}}}'

	if isinstance(e, RawInline):
		if e.format == "tex":
			return e.text
		else:
			return ""

	if isinstance(e, RawBlock):
		if e.format == "tex":
			return f'{e.text}\n'
		else:
			return ""
	
	if isinstance(e, Span) or isinstance(e, Plain):
		return tex(e.content, 0, "")

	if isinstance(e, LineItem):
		return tex(e.content, 0, "") + ("\\\\\n" if e.next else "\n")

	if isinstance(e, LineBlock):
		return f'{tex(e.content, indent_level+1, indent_str)}\n'

	if isinstance(e, Div):
		return f'{tex(e.content, indent_level+1, indent_str)}'

	if isinstance(e, Doc):
		return tex(e.content, indent_level, indent_str)+"\n\\bye"

	if isinstance(e, Inline):
		return f'\\{tag}{arguments}{open}{content_head}{tex(e.content, 0, "") if hasattr(e, "_content") else ""}{e.text if hasattr(e, "text") else ""}{content_foot}{close}'

	out_str = ""
	out_str = f"\\{tag}{arguments}{open}\n"
	out_str += content_head
	if hasattr(e, "_content"):
		out_str += tex(e.content, indent_level+1, indent_str)
	if hasattr(e, "text"):
		out_str += e.text
	out_str += f"{content_foot}\n{close}\n\n"

	return out_str