# Copyright 2020 Efabless Corporation
#
# 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
#
#      http://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 subprocess
import utils.utils as utils

parser = argparse.ArgumentParser(
    description="update configuration of design(s) per given PDK"
)

parser.add_argument(
    "--root",
    "-r",
    action="store",
    default="./",
    help="The root directory. assuming root/designs, root/scripts root/logs",
)

parser.add_argument(
    "--pdk", "-p", action="store", required=True, help="The name of the PDK"
)

parser.add_argument(
    "--std-cell-library",
    "-scl",
    action="store",
    required=True,
    help="The name of the standard cell library",
)


parser.add_argument("--designs", "-d", nargs="+", default=[], help="designs to update ")

parser.add_argument(
    "--best_results",
    "-b",
    action="store",
    required=True,
    help="name of the log file from which to extract the name of the best configs",
)

parser.add_argument(
    "--clean",
    "-cl",
    action="store_true",
    default=False,
    help="deletes the config file that the data was extracted from",
)

parser.add_argument(
    "--update_clock_period",
    "-ucp",
    action="store_true",
    default=False,
    help="Updates the CLOCK_PERIOD of the design based on the suggested_clock_period parameter",
)

args = parser.parse_args()
root = args.root
pdk = args.pdk
std_cell_library = args.std_cell_library
designs = list(dict.fromkeys(args.designs))
best_results = args.best_results
clean = args.clean
update_clock_period = args.update_clock_period

logFileOpener = open(root + "/regression_results/" + best_results, "r")
logFileData = logFileOpener.read().split("\n")
logFileOpener.close()


headerInfo = logFileData[0].split(",")
configIdx = 0
designIdx = 0
flow_statusIdx = 0
clkPeriodIdx = -1
for i in range(len(headerInfo)):
    if headerInfo[i] == "config":
        configIdx = i
        continue
    if headerInfo[i] == "design":
        designIdx = i
        continue
    if headerInfo[i] == "flow_status":
        flow_statusIdx = i
        continue
    if headerInfo[i] == "suggested_clock_period":
        clkPeriodIdx = i

designConfigDict = dict()
designFailDict = dict()
designClockDict = dict()

logFileData = logFileData[1:]

for line in logFileData:
    if line != "":
        splitLine = line.split(",")
        designConfigDict[str(splitLine[designIdx])] = str(splitLine[configIdx])
        designFailDict[str(splitLine[designIdx])] = (
            str(splitLine[flow_statusIdx]) == "flow_completed"
        )
        if clkPeriodIdx != -1:
            designClockDict[str(splitLine[designIdx])] = str(splitLine[clkPeriodIdx])

if len(designs) == 0:
    designs = [key for key in designConfigDict]

for design in designs:
    if design not in designConfigDict.keys():
        print(f"{design} not found in sheet. Skipping...")

    if not designFailDict[design]:
        print(f"Skipping {design} ...")
        continue

    print(f"Updating {design} config...")
    base_path = utils.get_design_path(design=design)
    configFileToUpdate = (
        str(base_path) + "/" + str(pdk) + "_" + str(std_cell_library) + "_config.tcl"
    )
    configFileBest = str(base_path) + "/" + str(designConfigDict[design]) + ".tcl"

    configFileBestOpener = open(configFileBest, "r")
    configFileBestData = configFileBestOpener.read().split("\n")
    configFileBestOpener.close()

    newData = ""
    copyFrom = False
    for line in configFileBestData:
        if line == "# Regression":
            copyFrom = True

        if copyFrom:
            newData += line + "\n"

    configFileToUpdateOpener = open(configFileToUpdate, "a+")
    configFileToUpdateOpener.write(newData)
    if update_clock_period:
        if design in designClockDict and float(designClockDict[design]) > 0:
            clockLine = (
                '\n# Suggested Clock Period:\nset ::env(CLOCK_PERIOD) "'
                + str(round(float(designClockDict[design]), 2))
                + '"\n'
            )
            configFileToUpdateOpener.write(clockLine)
    configFileToUpdateOpener.close()

    if clean:
        clean_cmd = f"rm -f {configFileBest}"
        subprocess.check_output(clean_cmd.split())
        # clean config file
