#!/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 json
import os
import pprint
import re
import shutil
import subprocess

from collections import defaultdict
from pathlib import Path

import common
from common import \
        lib_extract_from_name, \
        extract_version_and_lib_from_path, \
        copy_file_to_output, \
        \
        convert_libname, \
        convert_cell_fullname, \
        convert_pinname

from lef_canonical import canonicalize_lef, RE_MACRO, RE_PIN, RE_PIN_TYPE, RE_PIN_DIR


RE_COMMENT = re.compile(r'#.*$', re.MULTILINE)


def change_names_lef(new_lib, contents, extra=''):

    output = []
    info = {}

    last_macro_endpos = 0

    for macro in RE_MACRO.finditer(contents):
        between = contents[last_macro_endpos:macro.start(0)]
        if between.strip():
            output.append(('???', between))
        last_macro_endpos = macro.end(0)

        old_macroname = macro.group('cellname')
        old_lib, old_cellname = lib_extract_from_name(old_macroname)
        if not old_cellname.startswith(extra):
            assert extra not in old_cellname or 'probe' in old_cellname, (old_cellname, extra, old_macroname)
            assert old_lib, (old_macroname, old_lib, old_cellname)
            old_macroname = old_lib+'_'+extra+'_'+old_cellname

        new_macroname = convert_cell_fullname(old_macroname, new_lib)
        assert new_macroname.count('__') == 1, (new_macroname, old_macroname, new_lib)
        ext_lib, new_cell = new_macroname.split('__', 1)
        assert new_lib == ext_lib, (new_lib, ext_lib)

        content = macro.group('content')

        output_macro = []
        output.append((new_macroname, output_macro))
        output_macro.append(f'\nMACRO {new_macroname}\n')

        macro_info = {}
        assert new_macroname not in info, (new_macroname, info[newmacro_name])
        info[new_macroname] = macro_info

        last_pin_endpos = 0
        for pin in RE_PIN.finditer(content):
            between = content[last_pin_endpos:pin.start(0)]
            if between.strip():
                output_macro.append(between)
            last_pin_endpos = pin.end(0)

            old_pinname = pin.group('pinname')
            new_pinname = convert_pinname(old_pinname, new_macroname)
            pin_content = pin.group('content')

            pin_info = {}
            assert new_pinname not in pin_info, (new_pinname, pin_info[new_pinname])
            macro_info[new_pinname] = pin_info

            pin_dir = RE_PIN_DIR.search(pin_content)
            if pin_dir:
                pin_info['direction'] = pin_dir.group(1).strip()

            pin_type = RE_PIN_TYPE.search(pin_content)
            if pin_type:
                pin_info['type'] = pin_type.group(1).strip()
                if pin_info['type'] in ('POWER', 'GROUND') and 'direction' in pin_info:
                    del pin_info['direction']

            output_macro.append(f"  PIN {new_pinname}\n")
            output_macro.append(pin_content)
            output_macro.append(f"  END {new_pinname}\n")

        output_macro.append(content[last_pin_endpos:])
        output_macro.append(f'END {new_macroname}\n')

    return output, info


def filemain(input_path, temp_dir, final_dir, args):
    input_file = os.path.basename(input_path)
    if '_' in input_file:
        input_base, _ = input_file.split('.', 1)
        libname, extra = input_base.split('_', 1)
        if extra == 's8p':
            extra = 'lpflow'
        print("Extra:", extra)
    else:
        extra = ''

    tmp_lef = os.path.join(temp_dir, input_file)
    shutil.copyfile(input_path, tmp_lef)

    with open(tmp_lef) as in_f:
        contents = in_f.read()

    contents = RE_COMMENT.sub('', contents)
    out = contents

    old_lib, new_lib, ver = extract_version_and_lib_from_path(input_path)
    output, info = change_names_lef(new_lib, out, extra)

    header = output.pop(0)
    assert header[0] == '???', header
    header = header[1]
    header = "\n".join(x for x in header.splitlines() if x.strip() and not x.strip().startswith('#'))

    print("LEFs ----")
    for m in output:
        macroname, macrocontent = m
        assert macroname != '???', m

        macrocontent = canonicalize_lef(''.join(macrocontent))

        tmp_file = os.path.join(temp_dir, macroname+'.lef')
        assert not os.path.exists(tmp_file), tmp_file
        with open(tmp_file, 'w') as f:
            f.write(common.copyright_header['#'])
            f.write(header)
            f.write(macrocontent)

        copy_file_to_output(tmp_file, final_dir, new_lib, ver, macroname)
    print("---------")
    print()
    print("Pins ----")
    for macroname, macrodata in sorted(info.items()):
        tmp_file = os.path.join(temp_dir, macroname+'.lef.pins')
        assert not os.path.exists(tmp_file), tmp_file
        with open(tmp_file, 'w') as f:
            for pinname, pinprop in sorted(macrodata.items()):
                f.write(f"{pinname} ")
                f.write(" ".join(f"{a}={b}" for a, b in sorted(pinprop.items())))
                f.write("\n")
        copy_file_to_output(tmp_file, final_dir, new_lib, ver, macroname)
    print("---------")



if __name__ == "__main__":
    import doctest
    fails, _ = doctest.testmod()
    if fails>0:
        sys.exit(1)
    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(
        "temp",
        help="The path to the temp directory",
        type=Path)
    args = parser.parse_args()
    common.main('lef', filemain, args)
