#!/usr/bin/env python3

import os
import sys
import yaml
import subprocess

templ = """/*
:name: {0}
:description: {1}
:files: {2}
:incdirs: {3}
:top_module: {4}
:tags: {5}
:timeout: {6}
:compatible-runners: {7}
:allow_elaboration: {8}
*/
"""

try:
    tests_dir = os.environ['TESTS_DIR']
    conf_dir = os.environ['CONF_DIR']
except KeyError:
    print("Export the TESTS_DIR and CONF_DIR variables first")
    sys.exit(1)

try:
    tests_subdir = sys.argv[1]
except IndexError:
    print("Usage: ./generator <subdir>")
    sys.exit(1)

fusesoc_conf_subdir = "fusesoc-configs"
fusesoc_conf_files = os.listdir(
    os.path.abspath(os.path.join(conf_dir, fusesoc_conf_subdir)))

for fusesoc_conf_file in fusesoc_conf_files:
    fusesoc_conf_file = os.path.abspath(
        os.path.join(conf_dir, fusesoc_conf_subdir, fusesoc_conf_file))

    if not os.path.isfile(fusesoc_conf_file):
        continue

    with open(fusesoc_conf_file, 'r') as stream:
        try:
            yml_conf = yaml.safe_load(stream)
        except yaml.YAMLError as err:
            print(err)
            sys.exit(1)

    try:
        yml_conf["name"]
        yml_conf["description"]
        yml_conf["top_module"]
        yml_conf["tags"]
        yml_conf["path"]
        yml_conf["command"]
        yml_conf["conf_file"]
        yml_conf["test_file"]
        yml_conf["timeout"]
        yml_conf["compatible-runners"]
        yml_conf["allow_elaboration"]
    except KeyError as err:
        print("No key", err, "in file", fusesoc_conf_file)
        continue

    test_dir = os.path.join(tests_dir, 'generated', tests_subdir)

    if not os.path.isdir(test_dir):
        os.makedirs(test_dir, exist_ok=True)

    test_file = os.path.join(test_dir, yml_conf["test_file"])

    command_list = list(yml_conf["command"].split(" "))

    subprocess.call(
        command_list, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)

    core_conf_path = os.path.abspath(yml_conf["conf_file"])
    sources_path = os.path.dirname(core_conf_path)

    incdirs = ''
    sources = ''

    if core_conf_path.endswith(".vc") or core_conf_path.endswith(".scr"):
        with open(core_conf_path, "r") as f:
            for line in f:
                line = line.strip()
                if line.startswith("+incdir+"):
                    incdirs += os.path.join(
                        sources_path,
                        line.partition("+incdir+")[2]) + ' '
                elif (core_conf_path.endswith('.vc')
                      and line.startswith("--top-module")):
                    top_module = line.partition("--top-module ")[2]
                elif not line.startswith("-") and line:
                    sources += os.path.join(sources_path, line) + ' '
    elif core_conf_path.endswith(".tcl"):
        with open(core_conf_path, "r") as f:
            for line in f:
                line = line.strip()
                if line.startswith("read_verilog -sv "):
                    sources += os.path.join(
                        sources_path, line.replace("read_verilog -sv ",
                                                   "")) + " "
                elif line.startswith("set_property include_dirs "):
                    line.replace("set_property include_dirs ", "")
                    # Skip unnecessary information here, leave only paths to include dirs
                    split = line.split(" ")[3:-3]
                    for s in split:
                        incdirs += os.path.join(sources_path, s) + " "
    else:
        print(
            f"Unsupported config file: {core_conf_path}, currently supports only .vc, .scr and .tcl files"
        )
        sys.exit(1)

    # Fusesoc files dedicated for Verilator contains top module
    if not core_conf_path.endswith('.vc'):
        top_module = yml_conf["top_module"]

    with open(test_file, "w") as f:
        f.write(
            templ.format(
                yml_conf["name"], yml_conf["description"], sources, incdirs,
                top_module, yml_conf["tags"], yml_conf["timeout"],
                yml_conf["compatible-runners"], yml_conf["allow_elaboration"]))
