#!/usr/bin/env python3

import subprocess
import os
import sys
from os import path
import jinja2
from datetime import date
import shutil


COMMANDS = [
    "add-layer",
    "b",
    "build",
    "clean",
    "copy",
    "create",
    "data",
    "eval",
    "export-tar",
    "help",
    "help-macros",
    "import-docker",
    "import-lxc",
    "import-tar",
    "import-url",
    "init",
    "map",
    "mkdtemp",
    "mount",
    "nodepath",
    "parent",
    "purge",
    "rm",
    "run",
    "runb",
    "shrink",
    "sudo",
    "version",
    "with-mount",
]

ALIASES = [
    ("--help", "help"),
    ("-h", "help"),
    ("--help-macros", "help"),
    ("--version", "version"),
]

USAGE_DEF = '#define USAGE "usage: '
PROJECT_DIR = path.dirname(path.dirname(path.abspath(__file__)))
TESTS_DIR = path.join(PROJECT_DIR, "tests")
TEMPL_DIR = path.join(PROJECT_DIR, "www", "templates")
PLASH_EXECUTABLE = os.path.join("dist", "plash")


def parse_source(source_file):
    doc = []
    code = []
    found_code = False
    usage = None
    for line in open(source_file):
        if line.startswith("//") and not found_code:
            doc.append(line.lstrip("/ "))
        else:
            found_code = True
            code.append(line)
            if line.startswith(USAGE_DEF):
                usage = line[len(USAGE_DEF) : -4]

    doc_str = "".join(doc)
    code_str = "".join(code)

    try:
        doc_str, example = doc_str.split("Example:")
    except ValueError:
        example = ""

    return dict(doc=doc_str, code=code_str, example=example, usage=usage)


def parse_test(test_file):
    test_patterns = []
    for line in open(test_file):
        if line.startswith(": "):
            test_patterns.append(("label", line[2:]))
        else:
            test_patterns.append(("code", line))
    return test_patterns


def render(tpl_path, **context):
    path, filename = os.path.split(tpl_path)
    return (
        jinja2.Environment(loader=jinja2.FileSystemLoader(TEMPL_DIR))
        .get_template(filename)
        .render(context)
    )


def main():

    try:
        out_dir = sys.argv[1]
    except IndexError:
        print("usage: generate OUTDIR", file=sys.stderr)
        sys.exit(1)

    #
    # Copy images
    #
    shutil.copytree(
        path.join(PROJECT_DIR, "www", "images"),
        path.join(out_dir, "images"),
        dirs_exist_ok=True,
    )

    # check_call([path.join(TEMPL_DIR, "graph"), path.join(out_dir, "graph.svg")])

    #
    # generate the index.html
    #
    macros = subprocess.run(
        [PLASH_EXECUTABLE, "help-macros"], stderr=subprocess.PIPE
    ).stderr.decode()
    macros_list = [
        (a.strip(), b.strip())
        for (a, b) in [line.split(None, 1) for line in macros.splitlines()]
    ]
    help_out = subprocess.run(
        [PLASH_EXECUTABLE, "help"], stderr=subprocess.PIPE
    ).stderr.decode()
    progs = [i.split(None, 2)[1:] for i in help_out.splitlines()][:-1]
    with open(path.join(out_dir, "index.html"), "w") as f:
        f.write(
            render(
                "index.html", progs=progs, macros=macros_list, generated=date.today()
            )
        )

    #
    # generate the html for the commands
    #
    for cmd in COMMANDS:
        source_file = path.join(PROJECT_DIR, "src", cmd + ".c")
        test_file = path.join(os.path.join(TESTS_DIR, "command", cmd))
        with open(path.join(out_dir, cmd + ".html"), "w") as f:
            f.write(
                render(
                    "command.html",
                    **dict(
                        cmd=cmd,
                        **parse_source(source_file),
                        test_patterns=parse_test(test_file)
                    )
                )
            )

    for from_, to in ALIASES:
        try:
            os.link(path.join(out_dir, to + ".html"), path.join(out_dir, from_ + ".html"))
        except FileExistsError:
            pass


if __name__ == "__main__":
    main()
