# Path: topology_manager.py
# class TopologyManager(object):
#     def __init__(self, topology, social_graph, topology_nodes_position, enable_mobility = False, topology_file=None):
#         assert type(topology_nodes_position) == dict
# 
#         self.topology = topology
#         self.social_graph = social_graph
# 
#         self.enable_mobility = enable_mobility
#         
#         #Coordinates for the nodes and the users
#         #First: filter nodes without caching capabilities
#         tnp = {}
#         for n in topology_nodes_position.keys():
#             if self.has_request_capabilities(n):
#                tnp = topology_nodes_position[n]
#         topology_nodes_position = None 
# 
#         self.coords = tnp
#         self.coords_user = {}
# 
#         self.topology_nodes = {}
# 
#         self.method = None
#         self.topology_file = topology_file
#         self.initialize_paths()
# 
#     def initialize_paths(self):
#         if os.path.exists('graphs/'+self.topology_file+'.routes'):
#             self.paths = pickle.load(open('graphs/'+self.topology_file+'.routes', 'rb'))
#         else:
#             self.paths = SocialPaths(self.topology)
#             pickle.dump(self.paths, open('graphs/'+self.topology_file+'.routes', 'wb'))
# 
#     def get_path(self, social_src, social_dst):
#         return self.paths.calculate_path(self.topology_nodes[social_src], self.topology_nodes[social_dst])
# 
#     def set_method(self, method):
#         #Decide which method to use
#         assert method in ['random', 'geographical', 'onepublisher']
#         self.method = method
# 
#     def update_user_position(self, user, position):
#         # Assign new coords and then calculate user belonging to the topology_node.
#         self.coords_user[user] = position
#         if self.enable_mobility:
#         #if random.randint(0, 2) == 0:
#             self.topology_nodes[user] = self.closest_node(user)
# 
#     def update_user_node(self, user, node):
#         self.topology_nodes[user] = node
#     def get_user_node(self, user):
#         return self.topology_nodes[user]
# 
#     def update_all_users_position(self):
#         #TODO: add feature that users only can be putted in a node without the wr attribute as true
# 
#         if self.method == 'random':
#             request_nodes = [n for n in self.topology.nodes() if self.has_request_capabilities(n)]
#             res = []
#             for user in self.social_graph.nodes():
#                 self.topology_nodes[user] = random.choice(request_nodes)
# 
#         elif self.method == 'geographical':
#             for user in self.social_graph.nodes():
#                 self.topology_nodes[user] = self.closest_node(user)
# 
#         elif self.method == 'onepublisher':
#             for user in self.social_graph.nodes():
#                 self.topology_nodes[user] = 1
#             self.topology_nodes[0] = 0
#         else:
#             raise Exception('Not implemented method: %s'%self.method)
# 
#     def closest_node(self, user):
#         x, y = self.coords_user[user]
#         d = 100*100 # max distance
#         n = -2
#         for k,v in self.coords.items():
#             x1, y1 = v
# 
#             # Euclidean distance
#             a = numpy.array((x,y))
#             b = numpy.array((x1,y1))
#             d1 = numpy.linalg.norm(a-b)
# 
#             if d1 < d:
#                 d = d1
#                 n = k
#         assert n != -1, "Remember to set original coordinates for CCN nodes. User %s found closest node the -1"%user
#         return n
# 
#     def has_caching_capabilities(self, node):
#         n = self.topology.node[node]
#         return not (n.has_key('wc') and n['wc'] == True)
#     def has_request_capabilities(self, node):
#         n = self.topology.node[node]
#         return not (n.has_key('wr') and n['wr'] == True)
# 
#     def __getitem__(self, key):
#         return self.get_user_node(key)
#     def __setitem__(self, key, value):
#         return self.update_user_node(key, value)


import argparse
import networkx
import random
import re
from topology_manager import TopologyManager
    manager.update_all_users_position()

    #Run topology: initialization
    nodes_in_path = {}
    for node in topology_graph.nodes():
        nodes_in_path[int(node)] = {}
        for position in range(len(topology_graph.nodes())):
            nodes_in_path[int(node)][position] = 0

    #Run topology
    content = {}
    seq_file = file(args.trace_file, 'r')
    line = seq_file.readline()
    while line != '': #Empty line, we reach the end of the sequence
        result = re.match ("(?P<timestamp>[0-9]*\.[0-9]+)\t(?P<activity>Retrieve|Publish|retrieve|publish|Retrievecontent|Publishcontent)\t(?P<user>[0-9]+)\t\((?P<dependent>.*)\)\t\((?P<mobility_x>[0-9\.]*), ?(?P<mobility_y>[0-9\.]*)\)", line)
        if result != None:

            if result.group('activity').lower() in ['publishcontent', 'publish']:
                content[result.group('dependent').split(',')[0] ] = int(result.group('user'))
                #
            elif result.group(2).lower() in ['retrieve', 'retrievecontent']:
                src = int(result.group('user'))
                if central_repository:
                    dst = 0
                else:
                    dst = content[result.group('dependent').split(',')[0]]

                path = manager.get_path(src, dst)
                for i in range(0, len(path)):
                    user = path[i]

# Path: topology_manager.py
# class TopologyManager(object):
#     def __init__(self, topology, social_graph, topology_nodes_position, enable_mobility = False, topology_file=None):
#         assert type(topology_nodes_position) == dict
# 
#         self.topology = topology
#         self.social_graph = social_graph
# 
#         self.enable_mobility = enable_mobility
#         
#         #Coordinates for the nodes and the users
#         #First: filter nodes without caching capabilities
#         tnp = {}
#         for n in topology_nodes_position.keys():
#             if self.has_request_capabilities(n):
#                tnp = topology_nodes_position[n]
#         topology_nodes_position = None 
# 
#         self.coords = tnp
#         self.coords_user = {}
# 
#         self.topology_nodes = {}
# 
#         self.method = None
#         self.topology_file = topology_file
#         self.initialize_paths()
# 
#     def initialize_paths(self):
#         if os.path.exists('graphs/'+self.topology_file+'.routes'):
#             self.paths = pickle.load(open('graphs/'+self.topology_file+'.routes', 'rb'))
#         else:
#             self.paths = SocialPaths(self.topology)
#             pickle.dump(self.paths, open('graphs/'+self.topology_file+'.routes', 'wb'))
# 
#     def get_path(self, social_src, social_dst):
#         return self.paths.calculate_path(self.topology_nodes[social_src], self.topology_nodes[social_dst])
# 
#     def set_method(self, method):
#         #Decide which method to use
#         assert method in ['random', 'geographical', 'onepublisher']
#         self.method = method
# 
#     def update_user_position(self, user, position):
#         # Assign new coords and then calculate user belonging to the topology_node.
#         self.coords_user[user] = position
#         if self.enable_mobility:
#         #if random.randint(0, 2) == 0:
#             self.topology_nodes[user] = self.closest_node(user)
# 
#     def update_user_node(self, user, node):
#         self.topology_nodes[user] = node
#     def get_user_node(self, user):
#         return self.topology_nodes[user]
# 
#     def update_all_users_position(self):
#         #TODO: add feature that users only can be putted in a node without the wr attribute as true
# 
#         if self.method == 'random':
#             request_nodes = [n for n in self.topology.nodes() if self.has_request_capabilities(n)]
#             res = []
#             for user in self.social_graph.nodes():
#                 self.topology_nodes[user] = random.choice(request_nodes)
# 
#         elif self.method == 'geographical':
#             for user in self.social_graph.nodes():
#                 self.topology_nodes[user] = self.closest_node(user)
# 
#         elif self.method == 'onepublisher':
#             for user in self.social_graph.nodes():
#                 self.topology_nodes[user] = 1
#             self.topology_nodes[0] = 0
#         else:
#             raise Exception('Not implemented method: %s'%self.method)
# 
#     def closest_node(self, user):
#         x, y = self.coords_user[user]
#         d = 100*100 # max distance
#         n = -2
#         for k,v in self.coords.items():
#             x1, y1 = v
# 
#             # Euclidean distance
#             a = numpy.array((x,y))
#             b = numpy.array((x1,y1))
#             d1 = numpy.linalg.norm(a-b)
# 
#             if d1 < d:
#                 d = d1
#                 n = k
#         assert n != -1, "Remember to set original coordinates for CCN nodes. User %s found closest node the -1"%user
#         return n
# 
#     def has_caching_capabilities(self, node):
#         n = self.topology.node[node]
#         return not (n.has_key('wc') and n['wc'] == True)
#     def has_request_capabilities(self, node):
#         n = self.topology.node[node]
#         return not (n.has_key('wr') and n['wr'] == True)
# 
#     def __getitem__(self, key):
#         return self.get_user_node(key)
#     def __setitem__(self, key, value):
#         return self.update_user_node(key, value)


# Path: analyze_trace.py
import argparse
import networkx
import random
import re
from topology_manager import TopologyManager

    manager.update_all_users_position()

    #Run topology: initialization
    nodes_in_path = {}
    for node in topology_graph.nodes():
        nodes_in_path[int(node)] = {}
        for position in range(len(topology_graph.nodes())):
            nodes_in_path[int(node)][position] = 0

    #Run topology
    content = {}
    seq_file = file(args.trace_file, 'r')
    line = seq_file.readline()
    while line != '': #Empty line, we reach the end of the sequence
        result = re.match ("(?P<timestamp>[0-9]*\.[0-9]+)\t(?P<activity>Retrieve|Publish|retrieve|publish|Retrievecontent|Publishcontent)\t(?P<user>[0-9]+)\t\((?P<dependent>.*)\)\t\((?P<mobility_x>[0-9\.]*), ?(?P<mobility_y>[0-9\.]*)\)", line)
        if result != None:

            if result.group('activity').lower() in ['publishcontent', 'publish']:
                content[result.group('dependent').split(',')[0] ] = int(result.group('user'))
                #
            elif result.group(2).lower() in ['retrieve', 'retrievecontent']:
                src = int(result.group('user'))
                if central_repository:
                    dst = 0
                else:
                    dst = content[result.group('dependent').split(',')[0]]

                path = manager.get_path(src, dst)
                for i in range(0, len(path)):
                    user = path[i]

                    position = i