import argparse
import os
import re

from typing import TextIO


def get_file_name(path: str) -> str:
    idx = path.rfind("/")
    return path[idx+1:]


def navigation_bar(f: TextIO, challenges: list[str], idx: int, home_file: str):
    prv = get_file_name(challenges[idx - 1]) if idx > 0 else None
    nxt = get_file_name(challenges[idx + 1]) if idx < (len(challenges) - 1) else None
    oct_start = """<span class="navigation">{% octicon """
    oct_end = " height:24 %}</span>"
    dot = """<span class="navigation">{% octicon dot-fill %}</span>"""
    write(f, "\n")
    if prv:
        write(f, f"[{oct_start}chevron-left{oct_end}Previous Challenge]({prv}) {dot} ")
    write(f, f"**[{oct_start}home{oct_end}]({home_file})**")
    if nxt:
        write(f, f" {dot} [Next Challenge {oct_start}chevron-right{oct_end}]({nxt})")
    write(f, "\n")


def write(f: TextIO, line: str) -> str:
    f.write(line)


def process(filename: str, output_dir: str, student: bool):
    with open(filename, "r") as f:
        contents = iter(f.readlines())
    
    curr_line = next(contents)
    challenges_found = False
    challenge_files = []
    challenge_titles = []
    os.makedirs(output_dir, exist_ok=True)

    index_file = f"{output_dir}/README.md" if student else f"{output_dir}/solutions.md"
    challenges_header = "## Challenges" if student else "## Coach's Guides"
    with open(index_file, "w") as f:
        while not challenges_found:
            if curr_line.startswith(challenges_header):
                challenges_found = True
            else:
                write(f, curr_line)
                curr_line = next(contents)
        first_challenge_found = False
        while not first_challenge_found:
            if curr_line.startswith("## Challenge "):
                first_challenge_found = True
            else: 
                matches = re.match(r"-\s+Challenge (\d+): (.+)$", curr_line)
                if matches:
                    prefix = f"challenge-" if student else "solution-" 
                    challenge_no = int(matches.group(1))
                    challenge_file = f"{prefix}{challenge_no:02d}.md"
                    challenge_title = matches.group(2)
                    challenge_files.append(f"{output_dir}/{challenge_file}")
                    challenge_titles.append(f"# Challenge {challenge_no}: {challenge_title}")
                    write(f, f"- Challenge {challenge_no}: **[{challenge_title}]({challenge_file})**\n")
                else:
                    write(f, curr_line)
                curr_line = next(contents)
        home_file = "README.md" if student else "solutions.md"
        for idx, challenge in enumerate(challenge_files):
            with open(challenge, "w") as f:
                write(f, f"{challenge_titles[idx]}\n")
                # navigation top
                navigation_bar(f, challenge_files, idx, home_file)
                curr_line = next(contents, None)
                next_challenge_found = False
                while curr_line is not None and not next_challenge_found:
                    if curr_line.startswith("## Challenge "):
                        next_challenge_found = True
                        break
                    elif curr_line.startswith("#"):
                        write(f, curr_line[1:])
                    else:
                        write(f, curr_line)
                    curr_line = next(contents, None)
                # navigation bottom
                navigation_bar(f, challenge_files, idx, home_file)


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--output-dir", default="outputs")
    parser.add_argument("filename")
    args = parser.parse_args()

    process(args.filename, args.output_dir, True)
