# 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
