#!/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 os
import shutil
import argparse
from pathlib import Path

common_prefix="skywater-pdk/libraries"

versions = [ 'v0.10.0', 'v0.10.1', 'v0.11.0', 'v0.12.0', 'v0.12.1', 'v0.13.0', 'v0.20.0', 'v0.20.1']

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "output",
        help="The path to the output directory",
        type=Path)

    args = parser.parse_args()
    args.output = args.output.resolve()

    libs = args.output / common_prefix
    base_lib = libs / 'sky130_fd_pr_base'
    rf_lib = libs / 'sky130_fd_pr_rf'
    rf2_lib = libs / 'sky130_fd_pr_rf2'

    base_versions = [ v.name for v in base_lib.iterdir() if v.name.startswith('v') and v.is_dir() ]
    for v in base_versions:
        base_cells_path = base_lib / v / 'cells'
        rf_cells_path = rf_lib / v / 'cells'
        rf2_cells_path = rf2_lib / v / 'cells'
        do_rf = rf_cells_path.exists()
        do_rf2 = rf2_cells_path.exists()

        base_cells = set(base_cells_path.iterdir())
        base_cells_names = [ x.name for x in base_cells ]
        if do_rf:
            rf_cells = set(rf_cells_path.iterdir())
            rf_names = [ x.name for x in rf_cells ]

            for c in sorted(base_cells):
                if not c.is_dir():
                    continue
                if '.' in c.name:
                    continue
                if c.name in rf_names:
                    new_name = rf_lib / c.relative_to(base_lib)
                    for file in c.iterdir():
                        new_filename = file.name.replace('sky130_fd_pr_base', 'sky130_fd_pr_rf')
                        frm = str(file)
                        to = str(new_name / new_filename)

                        print(f"Move {frm} to {to}")

                        shutil.move(str(file), str(new_name / new_filename))

                    c.rmdir()

        if do_rf2:
            rf2_cells = set(rf2_cells_path.iterdir())
            rf2_names = [ x.name for x in rf2_cells ]

            for c in sorted(base_cells):
                if not c.is_dir():
                    continue
                if '.' in c.name:
                    continue
                if c.name in rf2_names:
                    new_name = rf2_lib / c.relative_to(base_lib)
                    for file in c.iterdir():
                        new_filename = file.name.replace('sky130_fd_pr_base', 'sky130_fd_pr_rf2')
                        frm = str(file)
                        to = str(new_name / new_filename)

                        print(f"Move {frm} to {to}")

                        shutil.move(str(file), str(new_name / new_filename))

                    c.rmdir()

