#!/usr/bin/env python3
import requests
import argparse
import os
import glob
import json
import yaml
import logging
import sys
import csv
import re
import jinja2

#GPIO_VALID_RANGE = [8, 36]
#GPIO_VALID_RANGE = [0, 38]
GPIO_VALID_RANGE = [0, 19]

def load_yaml(yaml_file):
    with open(yaml_file, "r") as stream:
        return (yaml.safe_load(stream))

def write_user_config(module_name, sources, io_ranges):
    env = jinja2.Environment(
        loader = jinja2.FileSystemLoader('verilog/rtl')
    )
    top_module_template = env.get_template('tiny_user_project.v.jinja2')
    with open('verilog/rtl/tiny_user_project.v', 'w') as fh:
        fh.write(top_module_template.render(
            module_name=module_name,
            io_in_range=io_ranges[0],
            io_out_range=io_ranges[1]
        ))
    user_defines_template = env.get_template('user_defines.v.jinja2')
    with open('verilog/rtl/user_defines.v', 'w') as fh:
        fh.write(user_defines_template.render(
            io_in_range=io_ranges[0],
            io_out_range=io_ranges[1]
        ))
    with open('openlane/tiny_user_project/config.json', 'r') as fh:
        config_json = json.load(fh)
    sources.append('verilog/rtl/defines.v')
    sources.append('verilog/rtl/tiny_user_project.v')
    config_json['VERILOG_FILES'] = [f'dir::../../{s}' for s in sources]
    with open('openlane/tiny_user_project/config.json', 'w') as fh:
        json.dump(config_json, fh, indent=4)

def get_project_source(yaml):
    # wokwi_id must be an int or 0
    try:
        wokwi_id = int(yaml['project']['wokwi_id'])
    except ValueError:
        logging.error("wokwi id must be an integer")
        exit(1)

    # it's a wokwi project
    if wokwi_id != 0:
        url = "https://wokwi.com/api/projects/{}/verilog".format(wokwi_id)
        logging.info("trying to download {}".format(url))
        r = requests.get(url)
        if r.status_code != 200:
            logging.warning("couldn't download {}".format(url))
            exit(1)

        filename = "user_module.v"
        with open(os.path.join('verilog/rtl', filename), 'wb') as fh:
            fh.write(r.content)

        # also fetch the wokwi diagram
        url = "https://wokwi.com/api/projects/{}/diagram.json".format(wokwi_id)
        logging.info("trying to download {}".format(url))
        r = requests.get(url)
        if r.status_code != 200:
            logging.warning("couldn't download {}".format(url))
            exit(1)

        with open(os.path.join('verilog/rtl', "wokwi_diagram.json"), 'wb') as fh:
            fh.write(r.content)

        return [f'verilog/rtl/{filename}', 'verilog/rtl/cells.v']

    # else it's HDL, so check source files
    else:
        if 'source_files' not in yaml['project']:
            logging.error("source files must be provided if wokwi_id is set to 0")
            exit(1)

        source_files = yaml['project']['source_files']
        if source_files is None:
            logging.error("must be more than 1 source file")
            exit(1)

        if len(source_files) == 0:
            logging.error("must be more than 1 source file")
            exit(1)

        if 'top_module' not in yaml['project']:
            logging.error("must provide a top module name")
            exit(1)

        return source_files


# documentation
def check_docs(yaml):
    for key in ['author', 'title', 'description', 'how_it_works', 'how_to_test', 'language']:
        if key not in yaml['documentation']:
            logging.error("missing key {} in documentation".format(key))
            exit(1)
        if yaml['documentation'][key] == "":
            logging.error("missing value for {} in documentation".format(key))
            exit(1)

    # if provided, check discord handle is valid
    if len(yaml['documentation']['discord']):
        parts = yaml['documentation']['discord'].split('#')
        if len(parts) != 2 or len(parts[0]) == 0 or not re.match('^[0-9]{4}$', parts[1]):
            logging.error(f'Invalid format for discord username')
            exit(1)


def get_top_module(yaml):
    wokwi_id = int(yaml['project']['wokwi_id'])
    if wokwi_id != 0:
        return "user_module_{}".format(wokwi_id)
    else:
        return yaml['project']['top_module']

def get_io_ranges(yaml):
    input_range = (GPIO_VALID_RANGE[0], GPIO_VALID_RANGE[0]+len(yaml['documentation']['inputs']))
#    output_range = (input_range[1], input_range[1]+len(yaml['documentation']['outputs']))
    output_range = (GPIO_VALID_RANGE[0], GPIO_VALID_RANGE[0]+len(yaml['documentation']['outputs']))
    gpio_end = output_range[1]
    if gpio_end > GPIO_VALID_RANGE[1]:
        raise Exception('ETOOMANY IOs')
    return (input_range, output_range)

def get_stats():
    with open('runs/wokwi/reports/metrics.csv') as f:
        report = list(csv.DictReader(f))[0]

    print('# Routing stats')
    print()
    print('| Utilisation | Wire length (um) |')
    print('|-------------|------------------|')
    print('| {} | {} |'.format(report['OpenDP_Util'], report['wire_length']))


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="TT setup")

    parser.add_argument('--check-docs', help="check the documentation part of the yaml", action="store_const", const=True)
    parser.add_argument('--get-stats', help="print some stats from the run", action="store_const", const=True)
    parser.add_argument('--create-user-config', help="create the user_config.tcl file with top module and source files", action="store_const", const=True)
    parser.add_argument('--debug', help="debug logging", action="store_const", dest="loglevel", const=logging.DEBUG, default=logging.INFO)
    parser.add_argument('--yaml', help="yaml file to load", default='info.yaml')

    args = parser.parse_args()
    # setup log
    log_format = logging.Formatter('%(asctime)s - %(module)-10s - %(levelname)-8s - %(message)s')
    # configure the client logging
    log = logging.getLogger('')
    # has to be set to debug as is the root logger
    log.setLevel(args.loglevel)

    # create console handler and set level to info
    ch = logging.StreamHandler(sys.stdout)
    # create formatter for console
    ch.setFormatter(log_format)
    log.addHandler(ch)

    if args.get_stats:
        get_stats()

    elif args.check_docs:
        logging.info("checking docs")
        config = load_yaml(args.yaml)
        check_docs(config)

    elif args.create_user_config:
        logging.info("creating include file")
        config = load_yaml(args.yaml)
        source_files = get_project_source(config)
        top_module = get_top_module(config)
        assert top_module != 'top'
        io_ranges = get_io_ranges(config)
        write_user_config(top_module, source_files, io_ranges)
