# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0

from collections import OrderedDict
from pathlib import Path
from typing import List

import hjson

# This file is $REPO_TOP/util/make_new_dif/ip.py, so it takes three parent()
# calls to get back to the top.
REPO_TOP = Path(__file__).resolve().parent.parent.parent


class Alert:
    """Holds alert information for populating DIF code templates.

    Attributes:
        name_snake (str): Alert short name in lower snake case.
        name_upper (str): Alert short name in upper snake case.
        name_camel (str): Alert short name in camel case.
        description (str): Full description of the alert.

    """

    def __init__(self, alert: OrderedDict) -> None:
        self.name_snake = alert["name"]
        self.name_upper = self.name_snake.upper()
        self.name_camel = "".join(
            [word.capitalize() for word in self.name_snake.split("_")])
        _multiline_description = alert["desc"][0].upper() + alert["desc"][1:]
        self.description = _multiline_description.replace("\n", " ")


class Irq:
    """Holds IRQ information for populating DIF code templates.

    Attributes:
        name_snake (str): IRQ short name in lower snake case.
        name_upper (str): IRQ short name in upper snake case.
        name_camel (str): IRQ short name in camel case.
        description (str): full description of the IRQ.

    """

    def __init__(self, irq: OrderedDict) -> None:
        self.name_snake = irq["name"]
        self.name_upper = self.name_snake.upper()
        self.name_camel = "".join(
            [word.capitalize() for word in self.name_snake.split("_")])
        _multiline_description = irq["desc"][0].upper() + irq["desc"][1:]
        self.description = _multiline_description.replace("\n", " ")
        self.width = irq["width"] if "width" in irq else 1


class Parameter:
    """Holds IP Parameter information for populating DIF code templates.

    Attributes:
        name (str): Parameter name.
        description (str): Parameter description.
        default (int): Default parameter value.

    """

    def __init__(self, parameter: OrderedDict) -> None:
        self.name = parameter["name"]
        self.description = parameter["desc"]
        self.default = None
        if "default" in parameter:
            self.default = parameter["default"]


class Ip:
    """Holds all IP metadata mined from an IP's name and HJSON file.

    Attributes:
        name_snake (str): IP short name in lower snake case.
        name_upper (str): IP short name in upper snake case.
        name_camel (str): IP short name in camel case.
        name_long_lower (str): IP full name in lower case.
        name_long_upper (str): IP full name with first letter capitalized.
        alerts (List[alerts]): List of Alert objs constructed from HSJON data.
        irqs (List[Irq]): List of Irq objs constructed from HJSON data.

    """

    def __init__(self, name_snake: str, name_long_lower: str,
                 templated_modules: List[str], ipgen_modules: List[str],
                 reggen_top_modules: List[str], top_name: str) -> None:
        """Mines metadata to populate this Ip object.

        Args:
            name_snake: IP short name in lower snake case (e.g., pwrmgr).
            name_long_lower: IP full name in lower case (e.g., power manager).
            templated_modules: Templated modules where hjson is under top_*
            ipgen_modules: Ipgen modules where hjson is under ip_autogen
            reggen_top_modules: Top Reggen modules where hjson is under top_*
        """
        # Generate various IP name formats.
        self.name_snake = name_snake
        self.name_upper = self.name_snake.upper()
        self.name_camel = "".join(
            [word.capitalize() for word in self.name_snake.split("_")])
        self.name_long_lower = name_long_lower
        # We just want to set the first character to title case. In particular,
        # .capitalize() does not do the right thing, since it would convert
        # UART to Uart.
        self.name_long_upper = (self.name_long_lower[0].upper() +
                                self.name_long_lower[1:])

        # Load HJSON data.
        if self.name_snake in ipgen_modules:
            data_dir = REPO_TOP / f"hw/{top_name}/ip_autogen/{self.name_snake}/data"
        elif self.name_snake in templated_modules:
            data_dir = REPO_TOP / f"hw/{top_name}/ip/{self.name_snake}/data/autogen"
        elif self.name_snake in reggen_top_modules:
            data_dir = REPO_TOP / f"hw/{top_name}/ip/{self.name_snake}/data/"
        else:
            data_dir = REPO_TOP / f"hw/ip/{self.name_snake}/data"
        _hjson_file = data_dir / f"{self.name_snake}.hjson"
        with _hjson_file.open("r") as f:
            _hjson_str = f.read()
        self._hjson_data = hjson.loads(_hjson_str)
        # Load Alert data from HJSON.
        self.alerts = self._load_alerts()
        # Load IRQ data from HJSON.
        self.irqs = self._load_irqs()
        # Load Parameters from HJSON
        self.parameters = self._load_parameters()

    def _load_alerts(self):
        assert (self._hjson_data and
                "ERROR: must load IP HJSON before loading Alerts")
        alerts = []
        if "alert_list" in self._hjson_data:
            for alert in self._hjson_data["alert_list"]:
                alerts.append(Alert(alert))
        return alerts

    def _load_irqs(self):
        assert (self._hjson_data and
                "ERROR: must load IP HJSON before loading IRQs")
        irqs = []
        if "interrupt_list" in self._hjson_data:
            for irq in self._hjson_data["interrupt_list"]:
                irqs.append(Irq(irq))
        return irqs

    def _load_parameters(self):
        assert (self._hjson_data and
                "ERROR: must load IP HJSON before loarding Parameters")
        parameters = {}
        if "param_list" in self._hjson_data:
            for parameter in self._hjson_data["param_list"]:
                p = Parameter(parameter)
                parameters[p.name] = p
        return parameters
