#!/bin/python
import argparse
import os
import re
import subprocess
import json
from collections import defaultdict
from pathlib import Path
from common import lib_extract_from_path, version_extract_from_path, convert_libname

sourcetodests = defaultdict(list)

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

def remap_path(old_path, input_dir, output_dir, lib_name, new_lib_name):
    """
    >>> remap_path('Dokumenty/SkyWater/skywater-src-nda/scs8hd/V0.0.1/lef/scs8hd.lef', 'Dokumenty/SkyWater/skywater-src-nda' ,'output', 'scs8hd', 'sky130_fd_sc_hd')
    'output/skywater-pdk/libraries/sky130_fd_sc_hd/V0.0.1/sky130_fd_sc_hd.lef'
    >>> remap_path('Dokumenty/SkyWater/skywater-src-nda/s8iom0s8/V0.1.0/lef/s8iom0s8.lef', 'Dokumenty/SkyWater/skywater-src-nda' ,'output', 's8iom0s8', 'sky130_fd_io')
    'output/skywater-pdk/libraries/sky130_fd_io/V0.1.0/sky130_fd_io.lef'
    >>> remap_path('Dokumenty/SkyWater/skywater-src-nda/s8fmlt/V0.1.0/lef/s8fmlt_16k_sys.lef', 'Dokumenty/SkyWater/skywater-src-nda' ,'output', 's8fmlt', 'sky130_fd_fmlt')
    'output/skywater-pdk/libraries/sky130_fd_fmlt/V0.1.0/sky130_fd_fmlt_16k_sys.lef'
    """
    parent_dir = str(input_dir).split("/")[-1]
    output_dir = str(output_dir)

    index = old_path.find(parent_dir) + len(parent_dir)

    target_dir, target_file = os.path.split(old_path[index:])
    new_path = output_dir +"/skywater-pdk/libraries" + target_dir.replace("/lef","") + "/"  + target_file

    assert lib_name != None and new_lib_name != None
    new_path = new_path.replace(lib_name, new_lib_name)

    return new_path

def rewrite_lef(lef_file, out_file):
    lef_file = os.path.abspath(lef_file)
    p = subprocess.Popen(['lefrw', '-o', out_file , lef_file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    stdout , stderr = p.communicate()
    ret = p.wait()
    if stderr != b'':
        print(stderr)
    return ret

def change_naming(contents, libi, new_lib_name):
    assert new_lib_name != None
    contents = contents.replace(lib, new_lib_name)

    return contents, new_lib_name

def main(lef_file, lib_name, new_lib_name, out_file=None):

    rewrite_lef(lef_file, 'temp.lef')
    with open('temp.lef') as in_f:
        contents = in_f.read()
    out, _ = change_naming(contents, lib_name, new_lib_name)
    out = re.sub(r"Parsed [0-9]* number of lines!![\n]", "", out)
    out = re.sub(r"MACRO\s+CLASS\s+[A-Z ]*[\n]", "", out)
    out = re.sub(r"DIVIDER (?P<div>.) ;", "DIVIDERCHAR \"\g<div>\" ;", out)
    out = Copyright_header + out

    if out_file is not None:
        dest_dir =  os.path.split(out_file)[0]
        if not os.path.isdir(dest_dir):
            os.makedirs(dest_dir)
        with open(out_file, 'w') as out_f:
            out_f.write(out)
    else:
        pass
        print(">>> Output:\n"+"_"*60+ "\n" + out)

if __name__ == "__main__":
    import doctest
    fails, _ = doctest.testmod()
    if fails>0:
        exit()
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "input",
        help="The path to the source directory/file",
        type=Path)
    parser.add_argument(
        "output",
        help="The path to the output directory",
        type=Path)
    parser.add_argument(
        "sourcetodests",
        help="output file mapping input to output",
        type=Path)
    args = parser.parse_args()
    if not os.path.isdir(args.input):
        lib = lib_extract_from_path(args.input)
        new_lib = convert_libname(lib)
        debug = True
        main(str(args.input), lib, new_lib)
    else:
        files = sorted(args.input.rglob('*.lef'))
        for f in files:
            f = str(f)
            if 'sram' in f or 'osu130' in f or 'openfpga' in f or 's8fmlt' in f:
                continue
            print(f)
            lib = lib_extract_from_path(f)
            new_lib = convert_libname(lib)
            out_f = remap_path(f, args.input, args.output, lib, new_lib)
            sourcetodests[f].append(out_f)
            main(f, lib, new_lib, out_f)
    os.remove('temp.lef')
    with open(args.sourcetodests, 'w') as srctodest:
        json.dump(sourcetodests, srctodest, indent=2)

