# Copyright (C) 2007 Adriano Monteiro Marques <py.adriano@gmail.com>
#
# Author: Joao Paulo de Souza Medeiros <ignotus21@gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA


class Node(object):
    """
    Node class
    """

    def __init__(self, id=None):
        """
        Constructor method of Node class
        @type  : integer
        @param : Node identificator
        """
        self.__id = id
        """Node identificator"""
        self.__information = None
        """Hash with general information"""


    def getID(self):
        """
        Get node ID
        @rtype: number
        @return: Node identificator
        """
        return self.__id


    def setID(self, id):
        """
        Set node ID
        @type  : number
        @param : Node identificator
        """
        self.__id = id


    def getInformation(self, info):
        """
        Get general information about node
        @type  : string
        @param : Information name
        @rtype: mixed
        @return: The requested information
        """
        return self.__information[ info ]


    def setInformation(self, info):
        """
        Set general information
        @type  : dict
        @param : General information dictionary
        """
        self.__information = info



class Graph:
    """
    Network Graph class
    """

    def __init__(self, nodes=None):
        """
        Constructor method of Graph class
        @type  : list
        @param : List of nodes
        """
        self.__mainNodeID = 0
        """"""
        self.__numberOfNodes = 0
        """"""
        self.__listOfNodes = []
        """"""
        self.__connections = set()
        """List with id's describing connections"""

        if nodes != None:
            self.__numberOfNodes = len(nodes)
            self.__createHashNode(nodes)


    def __createHashNode(self, nodes):
        """
        Create hash of nodes by node ID
        """
        self.__listOfNodes = range(self.__numberOfNodes)

        for i in range(self.__numberOfNodes):
            self.__listOfNodes[nodes[i].getID()] = nodes[i]


    def getNumberOfNodes(self):
        """
        Get the number of nodes in graph
        @rtype: number
        @return: The number of nodes in the graph
        """
        return self.__numberOfNodes


    def setMainNodeByID(self, id):
        """
        Set the main node by ID
        @type  : number
        @param : The node ID
        """
        self.__mainNodeID = id


    def getNodeByID(self, id):
        """
        Get one node of graph by your ID
        @type  : number
        @param : The node ID
        @rtype: Node
        @return: The node
        """
        return self.__listOfNodes[id]


    def getMainNode(self):
        """
        Get the main node
        @rtype: Node
        @return: The main node
        """
        return self.__listOfNodes[self.__mainNodeID]


    def getMainNodeID(self):
        """
        Get the main node ID
        @rtype: number
        @return: The main node ID
        """
        return self.__mainNodeID


    def setConnections(self, nodeIDA, nodeIDB):
        """
        Set node connections
        @type  : list
        @param : List of connections
        """
        connection = (nodeIDA, nodeIDB)
        self.__connections.add(connection)


    def getConnections(self):
        """
        """
        return self.__connections


    def getNodeConnections(self, node, exceptNodes=[]):
        """
        """
        nodeID = node.getID()
        connections = []

        for (a, b) in self.__connections:
            if a == nodeID and b not in exceptNodes:
                connections.append(b)
            if b == nodeID and a not in exceptNodes:
                connections.append(a)

        return connections

