import os, re, random, json
import subprocess
import sys

# for files templates you made
template_dir = "./templates/"
# for file templates generated by generator.py
gen_template_dir = "./gen-templates/"

temp_first: str = ""
temp_last: str = ""
with open(template_dir + "template.html", "r") as file:
    toggle: bool = True
    for line in file:
        if toggle:
            temp_first += line
            if "stylesheet" in line:
                temp_first += (
                    '<link rel="stylesheet" href="style.css?v='
                    + str(random.randint(0, 99999))
                    + '">'
                )
                # prevent stylesheet from getting cached
        else:
            temp_last += line
        if "main-content" in line:
            toggle = False


def find_text_between_delimiters(text: str) -> list[str]:
    # This regex will find all occurrences of text between ::
    pattern = r"(?s)::(.*?)(?=::)"
    matches = re.findall(pattern, text)
    return matches


data: dict[str, list[str]] = {}
flags = [False]


def handle_macros(line: str, flags: list[bool], html_string: str):
    if ">file::" in line:
        # insert files between file::<filename>:: if its specified in a div called codehead
        args = find_text_between_delimiters(line)
        path: str = args[0]
        html_string = html_string[:-7]
        html_string += " <a href=\"" + path + "\" class=\"file-link\">link to file</a></div>\n"
        html_string += "<pre><code>"
        
        max_lines: int = -1
        if len(args) > 1:
            max_lines = int(args[1])
        with open(path, "r") as file2:
            for l in file2:
                html_string += l.replace("<", "&lt;").replace(">", "&gt;")
                # replace <,> to be able to see html tags in literal files
                max_lines -= 1
                if max_lines == 0:
                    html_string += "...\nfile truncated"
                    break
        html_string += "</code></pre>"

    elif ">sorted::end::" in line and flags[0] is True:
        # this is starting to turn into a worse version of emacs org mode
        flags[0] = False
        data["el"].sort()
        if len(data["custom"]) > 0:
            try:
                json_data = json.loads("{" + data["custom"][0] + "}")
            except:
                raise RuntimeError("Bad json")
            _list: list[str] = data["el"]  # use _list in the sort command
            eval(json_data["sort-command"])
        for l in data["el"]:
            html_string += l
        data.clear()
        html_string += line
    elif flags[0] is True or ">sorted::begin::" in line:
        flags[0] = True
        if 'class="sorted-element"' in line:
            data["el"].append(line)
        elif ">sorted::begin::" in line:
            if len(data) > 0:
                raise RuntimeError("Data already in use")
            data["el"] = [""]
            data["custom"] = []
            args = find_text_between_delimiters(line)
            if len(args) == 2:
                data["custom"].append(args[1])
            return html_string
        else:
            data["el"][-1] += line

    return html_string

# for custom commands
custom = None
sys.path.append('./templates')

def process_line(line: str) -> list[str]:
    changed: bool = False
    if len(line) < 3:
        return [line]
    
    if line[0] == '!':
        changed = True
        line = "<!-- " + line + "-->"
        commands: list[str] = find_text_between_delimiters(line)
        for c in commands:
            exec(c)
    elif line[0] == '?' and line[1] == ':':
        changed = True
        commands: list[str] = find_text_between_delimiters(line)
        for c in commands:
            line = eval(c)
    elif line[0] == '?' and line[1] == '/':
        changed = True
        while not (line[-3] == '/' and line[-2] == '?' and line[-1] == '\n'):
            line += file.readline() # this is defined in process_template and somehow works still
        commands: list[str] = find_text_between_delimiters(line)
        for c in commands:
            line = eval(c)
    if changed:
        return line.split('\n')
    else:
        return [line]

def process_template(dir: str, filename: str):
    html_string: str = "<!-- GENERATED BY generator.py -->"
    html_string += temp_first
    with open(dir + filename, "r") as file:
        line = "yay"
        while line:
            line = file.readline()
            lines = process_line(line)
            for lin in lines:
                if sum(flags) == 0:  # all falses
                    html_string += lin
                elif sum(flags) > 1:
                    raise RuntimeError("Bad flags")
                if sum(flags) == 1 or 'class="block-head"' in lin:
                    html_string = handle_macros(lin, flags, html_string)
    html_string += temp_last
    with open(filename[:-6] + "html", "w") as file:
        file.write(html_string)

files: list[str] = os.listdir(template_dir)

def iterate_through_files(dir: str, files: list[str]):
    for file_ in files:
        if os.path.isdir(dir + file_) and file_[0] != "_":
            iterate_through_files(dir + file_ + "/", os.listdir(dir + file_))
        elif ".t.html" in file_:
            process_template(dir, file_)

subprocess.run(["mkdir", gen_template_dir])

# first pass, this could generate more templates
iterate_through_files(template_dir, files)

data: dict[str, list[str]] = {}
flags = [False]
new_files: list[str] = os.listdir(gen_template_dir)

# second pass
iterate_through_files(gen_template_dir, new_files)

subprocess.run(f"rm {gen_template_dir}/*", shell=True)
os.rmdir(gen_template_dir)