#! /usr/bin/python3

import argparse
from pathlib import Path
from jinja2 import Environment, select_autoescape, FileSystemLoader

import rospkg

PKG_PATH = Path(rospkg.RosPack().get_path("pal_create_app"))
AVAILABLE_TEMPLATES = {
    "python": {
        "tpl_path": "python_script",
        "short_desc": "simple Python script",
        "post_install_help": "Edit ./{path}/src/{id}/application_controller.py to implement your application logic.",
    }
}

TPL_EXT = "j2"


def get_intents():

    intents = []

    import rosmsg

    msg_def = rosmsg.get_msg_text("hri_actions_msgs/Intent", raw=True).split("\n")

    table = []
    in_table = False

    for l in msg_def:
        if "BEGIN_INTENTS_TABLE" in l:
            in_table = True
            continue
        if "END_INTENTS_TABLE" in l:
            break
        if in_table and "|" in l:
            table.append(l)

    if not table:
        rospy.logwarn(
            "Intent.msg not found or empty :-( Not generating the intents handling code"
        )
        return intents

    header = [
        h.strip(" *").lower().replace(" ", "_") for h in table[0].split("|")[1:-1]
    ]

    for l in table[1:]:
        entries = [e.strip(" `") for e in l.split("|")[1:-1]]

        # required thematic roles
        entries[2] = [x.strip().replace("`", "") for x in entries[2].split("-")[1:]]
        # optional thematic roles
        entries[3] = [x.strip().replace("`", "") for x in entries[3].split("-")[1:]]

        if not entries[0]:  # intent spanning multiple rows
            additional_data = dict(zip(header, entries))
            for h in header:
                intents[-1][h] += additional_data[h]
        else:
            intents.append(dict(zip(header, entries)))

    return intents


def interactive_create(id=None, template=None):

    while not id:
        id = input(
            "ID of your application? (must be a vlid identifier without spaces. eg 'robot_receptionist')\n"
        )

    name = input(
        "Full name of your application? (eg 'The Receptionist Robot', press Return to skip)\n"
    )
    if not name:
        name = id

    while not template:
        print("What kind of application controller do you want to create?")
        for idx, tpl in enumerate(AVAILABLE_TEMPLATES.keys()):
            print("%s: %s" % (idx + 1, AVAILABLE_TEMPLATES[tpl]["short_desc"]))

        try:
            choice = int(input("Your choice? "))

            template = list(AVAILABLE_TEMPLATES.keys())[choice - 1]
        except:
            template = ""

    return id, name, template


if __name__ == "__main__":

    parser = argparse.ArgumentParser(
        description="Generates application skeletons for interactive ROS-based robots"
    )
    #     parser.add_argument(
    #         "-f",
    #         "--force",
    #         action="store_true",
    #         help="if set, force overwriting existing documentation",
    #     )
    #
    parser.add_argument(
        "-i",
        "--id",
        type=str,
        nargs="?",
        help="ID of your application. Must be a valid file name without spaces.",
    )

    parser.add_argument(
        "-t",
        "--template",
        choices=AVAILABLE_TEMPLATES.keys(),
        type=str,
        nargs="?",
        help="Template to use.",
    )

    parser.add_argument(
        "path",
        type=str,
        nargs="?",
        const=".",
        default=".",
        help="path of the directory where the skeleton will be generated (default: .)",
    )

    args = parser.parse_args()

    intents = get_intents()

    id, name, tpl = interactive_create(args.id, args.template)

    data = {"id": id, "name": name, "intents": intents}

    root = Path(args.path) / id
    root.mkdir(parents=True, exist_ok=True)

    print("Generating application skeleton in %s..." % root)

    if tpl == "python":

        env = Environment(
            loader=FileSystemLoader(
                PKG_PATH / "tpl" / AVAILABLE_TEMPLATES[tpl]["tpl_path"]
            ),
            autoescape=select_autoescape(),
            trim_blocks=True,
        )

        tpls = env.list_templates(extensions=TPL_EXT)

        for tpl_name in tpls:
            j_tpl = env.get_template(tpl_name)
            tpl_name = tpl_name.replace("{{id}}", data["id"])
            filename = root / tpl_name[: -(1 + len(TPL_EXT))]
            filename.parent.mkdir(parents=True, exist_ok=True)
            print("Creating %s..." % filename)
            with open(filename, "w") as fh:
                fh.write(j_tpl.render(data))

        print("\n\033[32;1mDone!")
        print("\033[33;1m")
        print(AVAILABLE_TEMPLATES[tpl]["post_install_help"].format(path=root, id=id))
        print("\033[0m")

    else:
        print("No template for %s! Can not generate anything!" % tpl)
