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

import logging as log
from typing import Dict
from collections import OrderedDict

from .lib import *


def intersignal_format(uid: int, req: Dict, rsp: Dict) -> str:
    """Determine the signal format of the inter-module connections

    @param[uid] Unique ID. Each inter-signal has its own ID at top

    @param[req] Request struct. It has instance name, package format
                and etc.

    @param[rsp] Response struct. Same format as @param[req]
    """

    # TODO: Handle array signal
    result = "{req}_{rsp}_{struct}".format(req=req["inst_name"],
                                           rsp=rsp["inst_name"],
                                           struct=req["struct"])

    # check signal length if exceeds 100

    # 7 : space + .
    # 3 : _{i|o}(
    # 6 : _{req|rsp}),
    req_length = 7 + len(req["name"]) + 3 + len(result) + 6
    rsp_length = 7 + len(rsp["name"]) + 3 + len(result) + 6

    if max(req_length, rsp_length) > 100:
        logmsg = "signal {0} length cannot be greater than 100"
        log.warning(logmsg.format(result))
        log.warning("Please consider shorten the instance name")
    return result


def elab_intermodule(topcfg: OrderedDict):
    """Check the connection of inter-module and categorize them

    In the top template, it uses updated inter_module fields to create
    connections between the modules (incl. memories). This function is to
    create and check the validity of the connections `inter_module` using IPs'
    `inter_signal_list`.
    """

    list_of_intersignals = []

    if "inter_signal" not in topcfg:
        topcfg["inter_signal"] = OrderedDict()

    # Gather the inter_signal_list
    instances = topcfg["module"] + topcfg["memory"]

    intermodule_instances = [x for x in instances if "inter_signal_list" in x]

    for x in intermodule_instances:
        for sig in x["inter_signal_list"]:
            # Add instance name to the entry and add to list_of_intersignals
            sig["inst_name"] = x["name"]
            list_of_intersignals.append(sig)

    # TODO: Cross check

    # Add field to the topcfg
    topcfg["inter_signal"]["signals"] = list_of_intersignals

    # intermodule
    definitions = []

    uid = 0  # Unique connection ID across the top

    for req, rsps in topcfg["inter_module"].items():
        log.info("{req} --> {rsps}".format(req=req, rsps=rsps))
        req_module, req_signal = req.split('.')

        # get the module signal
        req_struct = find_intermodule_signal(list_of_intersignals, req_module,
                                             req_signal)

        rsp_len = len(rsps)
        for i, rsp in enumerate(rsps):
            assert i == 0, "Handling multiple connections (array) isn't yet supported"
            rsp_module, rsp_signal = rsp.split('.')

            rsp_struct = find_intermodule_signal(list_of_intersignals,
                                                 rsp_module, rsp_signal)

            # determine the signal name
            sig_name = "im{uid}_{req_s}".format(uid=uid,
                                                req_s=req_struct['struct'])
            sig_name = intersignal_format(uid, req_struct, rsp_struct)

            req_struct["top_signame"] = sig_name
            rsp_struct["top_signame"] = sig_name

            # Add to definitions
            if "package" in req_struct:
                package = req_struct["package"]
            else:
                assert "package" in rsp_struct, "Either req/rsp shall have 'package' field"
                package = rsp_struct["package"]

            definitions.append(
                OrderedDict([('package', package),
                             ('struct', req_struct["struct"]),
                             ('signame', sig_name),
                             ('type', req_struct["type"])]))

            if rsp_len != 1:
                log.warning("{req}[{i}] -> {rsp}".format(req=req, i=i,
                                                         rsp=rsp))
            else:
                log.warning("{req} -> {rsp}".format(req=req, rsp=rsp))

            # increase Unique ID
            uid += 1

    # TODO: Check unconnected port

    if "definitions" not in topcfg["inter_signal"]:
        topcfg["inter_signal"]["definitions"] = definitions


def find_intermodule_signal(sig_list, m_name, s_name) -> Dict:
    """Return the intermodule signal structure
    """

    filtered = [
        x for x in sig_list if x["name"] == s_name and x["inst_name"] == m_name
    ]

    assert len(
        filtered
    ) == 1, "Error on finding the inter module signal {m_name}.{s_name}".format(
        m_name=m_name, s_name=s_name)

    return filtered[0]
