# Copyright (c) 2012 Advanced Micro Devices, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

from topologies.BaseTopology import BaseTopology

class Cluster(BaseTopology):
    """ A cluster is a group of nodes which are all one hop from eachother
        Clusters can also contain other clusters
        When creating this kind of topology, return a single cluster (usually
        the root cluster) from create_system in configs/ruby/<protocol>.py
    """

    _num_int_links = 0
    _num_ext_links = 0
    _num_routers = 0

    # Below methods for auto counting
    @classmethod
    def num_int_links(cls):
        cls._num_int_links += 1
        return cls._num_int_links - 1
    @classmethod
    def num_ext_links(cls):
        cls._num_ext_links += 1
        return cls._num_ext_links - 1
    @classmethod
    def num_routers(cls):
        cls._num_routers += 1
        return cls._num_routers - 1

    def __init__(self, intBW=0, extBW=0, intLatency=0, extLatency=0):
        """ internalBandwidth is bandwidth of all links within the cluster
            externalBandwidth is bandwidth from this cluster to any cluster
                connecting to it.
            internal/externalLatency are similar
            **** When creating a cluster with sub-clusters, the sub-cluster
                 external bandwidth overrides the internal bandwidth of the
                 super cluster
        """
        self.nodes = []
        self.router = None # created in makeTopology
        self.intBW = intBW
        self.extBW = extBW
        self.intLatency = intLatency
        self.extLatency = extLatency

    def add(self, node):
        self.nodes.append(node)

    def makeTopology(self, options, network, IntLink, ExtLink, Router):
        """ Recursively make all of the links and routers
        """

        # make a router to connect all of the nodes
        self.router = Router(router_id=self.num_routers())
        network.routers.append(self.router)

        for node in self.nodes:
            if type(node) == Cluster:
                node.makeTopology(options, network, IntLink,
                                  ExtLink, Router)

                # connect this cluster to the router
                link_out = IntLink(link_id=self.num_int_links(), src_node=self.router,
                           dst_node=node.router)
                link_in = IntLink(link_id=self.num_int_links(), src_node=node.router,
                                  dst_node=self.router)

                if node.extBW:
                    link_out.bandwidth_factor = node.extBW
                    link_in.bandwidth_factor = node.extBW

                # if there is an internal b/w for this node
                # and no ext b/w to override
                elif self.intBW:
                    link_out.bandwidth_factor = self.intBW
                    link_in.bandwidth_factor = self.intBW

                if node.extLatency:
                    link_out.latency = node.extLatency
                    link_in.latency = node.extLatency
                elif self.intLatency:
                    link_out.latency = self.intLatency
                    link_in.latency = self.intLatency

                network.int_links.append(link_out)
                network.int_links.append(link_in)
            else:
                # node is just a controller,
                # connect it to the router via a ext_link
                link = ExtLink(link_id=self.num_ext_links(), ext_node=node,
                        int_node=self.router)

                if self.intBW:
                    link.bandwidth_factor = self.intBW
                if self.intLatency:
                    link.latency = self.intLatency

                network.ext_links.append(link)

    def __len__(self):
        return len([i for i in self.nodes if type(i) != Cluster]) + \
               sum([len(i) for i in self.nodes if type(i) == Cluster])
