#!/usr/bin/env python3
# Copyright 2020 The Skywater PDK Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


import argparse
import os
import re
import simplejson as json
import subprocess
import sys

from multiprocessing import Pool
from pathlib import Path


def call_with_retcode(cmd):
    print(cmd)
    p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    stdout, stderr = p.communicate()

    stdout = stdout.decode("utf-8")
    stderr = stderr.decode("utf-8")

    retcode = p.wait()
    print()
    print('='*5)
    print(stdout)
    print('-'*5)
    print(stderr)
    print(retcode, '='*5)
    print()

    return retcode, stderr


def use_netlistsvg(json_file, out_file):
    """Draw module schematics using netlistsvg. Operates on json files. returns retcode"""
    cmd = ["netlistsvg", json_file, "-o", out_file]
    return call_with_retcode(cmd)


def use_yosys(command, files):
    """Execute yosys command, returns retcode"""

    defines = {
        'FUNCTIONAL':    '=1',  # Want the functional model
        'NO_PRIMITIVES': '=1',  # Yosys doesn't support primitives
        'UNIT_DELAY':    '',    # Yosys doesn't support delays
    }
    actions = " ".join([
        "verilog_defines " + " ".join("-D{}{}".format(a, b) for a, b in defines.items()) + ";",
        "read_verilog " + " ".join(files) + ";",
        "hierarchy -check -auto-top; " + command,
    ])
    cmd = ["yosys", "-f", "verilog",  "-p",  actions]
    return call_with_retcode(cmd)


def draw_schematics(verilog_path):
    """Draw module schematics using yosys+netlistsvg. Operates on verilog files.
    Output file is placed in same directory as input"""

    verilog_path = str(verilog_path)
    verilog_dir = os.path.dirname(verilog_path)
    verilog_file = os.path.basename(verilog_path)

    verilog_base = verilog_file.split('.', 1)[0]

    verilog_json = os.path.join(verilog_dir, verilog_base+".json")
    verilog_schematic = os.path.join(verilog_dir, verilog_base+".schematic.svg")

    print("Generating schematic for", str(verilog_path))

    retcode, err = use_yosys(
        #"prep; splitinout; write_json {}.json" % verilog_base,
        "prep; write_json -compat-int {}".format(verilog_json),
        [verilog_path],
    )
    if retcode != 0:
        return verilog_path, err

    json_data = ""
    with open(verilog_json, "r") as f:
        contents = f.read()
    contents = re.sub('"type": "[^/"]+__', '"type": "', contents)
    contents = re.sub('("[^"]*)\\.\\./[^/]*/skywater-pdk/libraries/[^/]*/v[^/]*/', '\\1./', contents)
    with open(verilog_json, "w") as f:
        f.write(contents)

    retcode, err = use_netlistsvg(verilog_json, verilog_schematic)
    if retcode != 0:
        return verilog_path, err

    return verilog_path, None


def files(p):
    for f in p.rglob("*.v"):
        d = str(f).split('/')

        filename = d.pop(-1)
        cell = d.pop(-1)

        x = d.pop(-1)
        if x != 'cells':
            continue
        ver = d.pop(-1)
        lib = d.pop(-1)

        o = lib + '__' + cell + '.v'
        if filename != o:
            continue
        yield str(f)


# def split_inouts(in_file, out_file = None):
#     """Split inout ports into inputs and outputs. Operates on yosys json files"""
#     if out_file == None:
#         out_file = in_file
#     with open(in_file, 'r') as in_f:
#         design = json.load(in_f)
#     top_name = split_io.find_top_module(design)
#     port_map, net_map = split_io.find_and_split_inout_ports_and_nets(design, top_name)
#     output = json.dumps(design, sort_keys=True, indent=2)
#     output = re.sub(r'"00000000000000000000000000000001"', "1", output)
#     with open(out_file, 'w') as out_f:
#        out_f.write(output)


if __name__ == "__main__":
    for a in sys.argv[1:]:
        if os.path.isfile(a):
            draw_schematics(a)
            continue
        assert os.path.exists(a), a
        p = Path(a)
        print(p)
        pool = Pool()
        for verilog_path, err in pool.imap_unordered(draw_schematics, files(p)):
            if err is not None:
                msg = err + "\nError creating schematic file for:" + verilog_path+'\n\n'
                print(msg, file=sys.stderr, flush=True)
            else:
                print("Finished creating schematic file for:", verilog_path)
        pool.close()
        pool.join()
