# 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 List

from .item import Edge, Node, NodeType

#Nodes = List[Node]
#Edges = List[Edge]
#Clocks = List[str]


class Xbar:
    """Xbar contains configurations to generate TL-UL crossbar.
    """
    nodes = []  # Nodes
    edges = []  # Edges
    clock = ""  # str  # Main clock remove 'clk_' prefix
    name = ""  # str  # e.g. "main" --> main_xbar
    clocks = []  # Clocks
    # 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 = []

    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
