# 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 .item import Edge, NodeType


class Xbar:
    """Xbar contains configurations to generate TL-UL crossbar.
    """
    nodes = []  # Nodes
    edges = []  # Edges
    clock = ""  # str  # primary clock of xbar
    reset = ""  # str  # primary reset of xbar
    name = ""  # str  # e.g. "main" --> main_xbar
    clocks = []  # All clocks of xbar
    resets = []  # All resets of xbar
    ip_path = ""  # additional path to generated rtl/dv folders: outdir/ip_path/rtl

    # prefix is useful if SoC has more than one Xbar

    # variables after elaboration. Shouldn't be touched by outside
    blocks = []  # Nodes  # Internal blocks

    def __init__(self):
        self.blocks = []
        self.nodes = []
        self.edges = []
        self.clocks = []
        self.resets = []

    def __repr__(self):
        out = "<Xbar(%s) #nodes:%d clock:%s" % (self.name, len(
            self.nodes), self.clock)
        out += " #edges:%d>\n" % (len(self.edges))

        # print nodes
        out += "  Nodes:\n"
        for node in self.nodes:
            out += "    - " + node.name + "\n"

        out += "  Edges:\n"
        for edge in self.edges:
            out += "    - " + edge.us.name + " => " + edge.ds.name + "\n"
        # print edges
        return out

    def get_edges_from_node(self, node):  # Node -> Edges
        return [
            edge for edge in self.edges
            if node.name in (edge.us.name, edge.ns.name)
        ]

    def get_node(self, node):  # str -> Node
        result = [x for x in self.nodes if x.name == node]
        if len(result) != 1:
            raise  # Exception

        return result[0]

    @property
    def hosts(self):
        return [x for x in self.nodes if x.node_type == NodeType.HOST]

    @property
    def devices(self):
        return [x for x in self.nodes if x.node_type == NodeType.DEVICE]

    @property
    def socket_1ns(self):
        return [x for x in self.nodes if x.node_type == NodeType.SOCKET_1N]

    def get_downstream_device(self, node):  # Node -> Node
        if (node.node_type == NodeType.DEVICE):
            return node

        if len(node.ds) == 0:
            log.error(
                "Node (%s) doesn't have downstream Node: US(%s), DS(%s)" %
                (node.name, ' '.join(map(repr, node.us)), ' '.join(
                    map(repr, node.ds))))
        return self.get_downstream_device(node.ds[0].ds)

    def get_downstream_device_from_edge(self, edge):  # Edge -> Node
        return self.get_downstream_device(edge.ds)

    def get_leaf_from_s1n(self, node, idx):  # Node -> int -> Node
        """ get end-device node from Socket_1n's Downstream port

        Current implementation can't have multiple devices under the tree of
        one downstream port in Socket_1N
        """
        return self.get_downstream_device(node.ds[idx].ds)

    def get_s1n_if_exist(self, node):  # Node -> Node
        """ return SOCKET_1N if exists down from the node, if not return itself
        """
        if node.node_type == NodeType.DEVICE:
            log.error("get_s1n_if_exist hits DEVICE type (unexpected)")
            return node
        if node.node_type == NodeType.SOCKET_1N:
            return node
        return self.get_s1n_if_exist(node.ds[0].ds)

    def get_leaf_from_node(self, node, idx):  # Node -> int -> Node
        """ get end device node from any node, idx is given to look down.
        """
        num_dev = len(self.get_s1n_if_exist(node).ds)
        if idx >= num_dev:
            log.error(
                "given index is greater than number of devices under the node")

        return self.get_leaf_from_s1n(self.get_s1n_if_exist(node), idx)

    def get_devices_from_host(self, host):  # Node -> Nodes
        devices = list(
            map(self.get_downstream_device_from_edge,
                self.get_s1n_if_exist(host).ds))

        return devices

    def get_addr(self, device):  # Node -> Tuple[int,int]
        if device.node_type != NodeType.DEVICE:
            log.error("get_addr receives non DEVICE type node")

        return (device.address_from, device.address_to)

    def connect_nodes(self, u_node, d_node):  # str -> str -> bool
        # Create edges between Nodes
        # Return false if Nodes aren't exist or same connection exists
        upNode = self.get_node(u_node)
        dnNode = self.get_node(d_node)

        edge = Edge(upNode, dnNode)

        if any([
                e.us.name == edge.us.name and e.ds.name == edge.ds.name
                for e in self.edges
        ]):
            return False

        self.edges.append(edge)

        upNode.ds.append(edge)
        dnNode.us.append(edge)

        return True

    def insert_node(self, new_node, node):
        if new_node.node_type == NodeType.ASYNC_FIFO:
            if node.node_type == NodeType.HOST:
                # Insert node to downstream
                edge = Edge(node, new_node)
                new_node.ds = node.ds
                node.ds = [edge]
                new_node.us = [edge]
                self.nodes.append(new_node)
                self.edges.append(edge)
                for e in new_node.ds:
                    # replace us to new_node
                    e.us = new_node
            elif node.node_type == NodeType.DEVICE:
                # insert node to upstream
                edge = Edge(new_node, node)
                new_node.us = node.us
                new_node.ds = node
                node.us = [edge]
                new_node.ds = [edge]
                self.nodes.append(new_node)
                self.edges.append(edge)
                for e in new_node.us:
                    # replace us to new_node
                    e.ds = new_node
            else:
                raise
        elif new_node.node_type == NodeType.SOCKET_M1:
            # Revise every upstream
            edge = Edge(new_node, node)
            new_node.us = node.us
            node.us = [edge]
            new_node.ds = [edge]
            self.nodes.append(new_node)
            self.edges.append(edge)
            for e in new_node.us:
                e.ds = new_node

        elif new_node.node_type == NodeType.SOCKET_1N:
            # Revise every downstream
            edge = Edge(node, new_node)
            new_node.ds = node.ds
            node.ds = [edge]
            new_node.us = [edge]
            # TODO: add new_node.us logic
            self.nodes.append(new_node)
            self.edges.append(edge)
            for e in new_node.ds:
                e.us = new_node
        else:
            # Caller passes HOST or DEVICE as a new node. Error!
            log.error(
                "Xbar.insert_node is called with HOST or DEVICE: %s. Ignored" %
                (new_node.name))

        return self

    def repr_tree(self, node, indent):
        """string format of tree connection from node to devices

        Desired output:
        host_a
          -> asf_nn
            -> s1n_nn
              -> sm1_mm
                -> device_c
              -> sm1_nn
                -> device_b

        """
        out = "// "
        if indent != 0:
            # not First
            out += ' ' * indent + '-> '

        out += node.name

        if node.node_type != NodeType.DEVICE:
            # still more nodes exist under this node
            for ds in node.ds:
                out += '\n'
                out += self.repr_tree(ds.ds, indent + 2)

        return out
