# Copyright 2020-2021 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 os
import subprocess
import sys

sys.path.append(os.path.dirname(os.path.dirname(__file__)))

from utils.utils import get_run_path, get_design_path  # noqa: E402
from shutil import copyfile  # noqa: E402
from collections import OrderedDict  # noqa: E402


class ConfigHandler:
    config_getter_script = os.path.join(os.path.dirname(__file__), "config_get.sh")

    configuration_values = [
        "CLOCK_PERIOD",
        "SYNTH_STRATEGY",
        "SYNTH_MAX_FANOUT",
        "FP_CORE_UTIL",
        "FP_ASPECT_RATIO",
        "FP_PDN_VPITCH",
        "FP_PDN_HPITCH",
        "PL_TARGET_DENSITY",
        "GLB_RT_ADJUSTMENT",
        "STD_CELL_LIBRARY",
        "CELL_PAD",
        "DIODE_INSERTION_STRATEGY",
    ]

    configuration_files = [
        "synthesis.tcl",
        "floorplan.tcl",
        "placement.tcl",
        "cts.tcl",
        "routing.tcl",
        # "magic.tcl",
    ]

    @classmethod
    def update_configuration_values(Self, params, append):
        if append:
            Self.configuration_values = Self.configuration_values + params
        else:
            Self.configuration_values = params
        Self.configuration_values = list(
            OrderedDict.fromkeys(Self.configuration_values)
        )

    @classmethod
    def update_configuration_values_to_all(Self, append):
        config_relative_path = "configuration"
        config_path = os.path.join(os.getcwd(), config_relative_path)
        if not append:
            Self.configuration_values = []

        for file in Self.configuration_files:
            try:
                file_string = open(os.path.join(config_path, file), "r").read()
                file_lines = file_string.split("\n")
                for line in file_lines:
                    start = line.find("(")
                    end = line.find(")")
                    if (start > -1) & (end > 0) & (line.find("SCRIPT") == -1):
                        Self.configuration_values.append(line[start + 1 : end])
            except OSError:
                print("Could not open/read file:", config_path)
                sys.exit()
        Self.configuration_values = list(dict.fromkeys(Self.configuration_values))

    @classmethod
    def get_header(Self):
        return ",".join(Self.configuration_values)

    @classmethod
    def get_config(Self, design, tag, run_path=None):
        if run_path is None:
            run_path = get_run_path(design=design, tag=tag)
        config_relative_path = "config.tcl"
        config_path = os.path.join(os.getcwd(), run_path, config_relative_path)
        config_coded = subprocess.check_output(
            [Self.config_getter_script, config_path, *Self.configuration_values]
        )
        config = config_coded.decode(sys.getfilesystemencoding()).strip()
        config = config.split("##")
        config = list(filter(None, config))
        config = [element.strip('{}"') for element in config]
        return config

    @staticmethod
    def gen_base_config(design, base_config_file):
        config_file = os.path.join(get_design_path(design=design), "config.tcl")
        copyfile(config_file, base_config_file)
