import argparse
import os


parser = argparse.ArgumentParser(
    description="Generate a skeleton project for a Langkit-based language"
                " engine"
)
parser.add_argument(
    "language", help="Name of the target language (camel case)")


def generate(lang_name):
    lang_name_slug = lang_name.lower()

    template_args = {
        "lang_name": lang_name,
        "lang_name_repr": repr(lang_name),
        "lang_name_slug": lang_name_slug,
    }

    # Create the directories...
    os.mkdir(lang_name_slug)
    os.chdir(lang_name_slug)
    os.mkdir("language")

    # ... and the 4 initial files.
    for filename, template in [
        ("manage.py", MANAGE_TEMPLATE),
        (os.path.join("language", "__init__.py"), ""),
        (os.path.join("language", "lexer.py"), LEXER_TEMPLATE),
        (os.path.join("language", "parser.py"), PARSER_TEMPLATE),
    ]:
        with open(filename, "w") as f:
            f.write(template.format(**template_args))

    os.chmod("manage.py", 0o755)


MANAGE_TEMPLATE = """#! /usr/bin/env python

import os

from langkit.libmanage import ManageScript


class Manage(ManageScript):
    def create_context(self, args):
        from langkit.compile_context import CompileCtx

        from language.lexer import {lang_name_slug}_lexer
        from language.parser import {lang_name_slug}_grammar

        return CompileCtx(lang_name={lang_name_repr},
                          lexer={lang_name_slug}_lexer,
                          grammar={lang_name_slug}_grammar,
                          verbosity=args.verbosity)

if __name__ == "__main__":
    Manage().run()
"""


LEXER_TEMPLATE = """\
from langkit.lexer import Lexer, LexerToken, Literal, WithText


class Token(LexerToken):
    Example = WithText()

{lang_name_slug}_lexer = Lexer(Token)
{lang_name_slug}_lexer.add_rules(
    (Literal("example"), Token.Example),
)
"""


PARSER_TEMPLATE = """\
from langkit.dsl import ASTNode, abstract
from langkit.parsers import Grammar


@abstract
class {lang_name}Node(ASTNode):
    \"\"\"
    Root node class for {lang_name} AST nodes.
    \"\"\"
    pass

class ExampleNode({lang_name}Node):
    \"\"\"
    Example node.
    \"\"\"
    pass

{lang_name_slug}_grammar = Grammar("main_rule")
{lang_name_slug}_grammar.add_rules(
    main_rule=ExampleNode("example")
)
"""


def main():
    generate(parser.parse_args().language)
