def __init__(self):
     print("ImportNetLogoWorld created");
     self.fileNameIn = None;
     self.fileIn = None;
     # sub csv tables names in netlogo wolrd file
     self.streamsNames = [ImportNetLogoWorld.TYPE_TURTLES, ImportNetLogoWorld.TYPE_LINKS, ImportNetLogoWorld.TYPE_PATCHES];
     self.demultiplexingContex = TextDemultiplexer.newDict();
     self.demultiplexingContex['type'] = None;
     self.textDemultiplexer = None;
     self.netLogoWorld = NetLogoWorld();
     self.nParams = None;
     self.eParams = None;
class ImportNetLogoWorld(object):
    TYPE_TURTLES = "TURTLES";
    TYPE_LINKS = "LINKS";
    TYPE_PATCHES = "PATCHES";
    #PARAMS_TURTLES = ['who', 'color', 'heading', 'xcor', 'ycor', 'shape', 'label', 'label-color', 'breed', 'hidden?', 'size', 'pen-size', 'pen-mode'];
    #PARAMS_TURTLES_EXTRA = ['popularity', 'calculation_actor_1', 'calculation_actor_2', 'calculation_actor_3'];
    #PARAMS_TURTLES_FORBIDDEN = ['id', 'name'];
    #PARAMS_LINKS_EXTRA = ['calculation_fs_1', 'calculation_fs_2', 'calculation_fs_3', \
    #                      'calculation_fs_1-end1', 'calculation_fs_2-end1', 'calculation_fs_3-end1', \
    #                      'calculation_fs_1-end2', 'calculation_fs_2-end2', 'calculation_fs_3-end2'];
    
    @staticmethod
    def getElementIndexInList(element, list_element):
        try:
            index_element = list_element.index(element)
            return index_element
        except ValueError:
            return -1
        
    def __init__(self):
        print("ImportNetLogoWorld created");
        self.fileNameIn = None;
        self.fileIn = None;
        # sub csv tables names in netlogo wolrd file
        self.streamsNames = [ImportNetLogoWorld.TYPE_TURTLES, ImportNetLogoWorld.TYPE_LINKS, ImportNetLogoWorld.TYPE_PATCHES];
        self.demultiplexingContex = TextDemultiplexer.newDict();
        self.demultiplexingContex['type'] = None;
        self.textDemultiplexer = None;
        self.netLogoWorld = NetLogoWorld();
        self.nParams = None;
        self.eParams = None;

    def importWorld(self, fileNameIn, nParams, eParams):
        self.fileNameIn = fileNameIn;
        self.nParams = nParams;
        self.eParams = eParams;
        print("Importing started ...");
        
        self.fileIn = open(self.fileNameIn);
        self.textDemultiplexer = TextDemultiplexer();
        self.textDemultiplexer.init(self.fileIn, self.streamsNames);
        self.textDemultiplexer.demultiplex(self.demultiplexedLine, self.demultiplexingContex);
        
        self.loadComponents();
        print("Importing finished ...");
        return self.netLogoWorld;

    def splitParams(self, additionalColumns):
        columnNames = [];
        columnTypes =TextDemultiplexer.newDict();
        for columnNameExtra in additionalColumns:
            if(columnNameExtra.find(":") < 0): columnNameExtra += ":string"; 
            (columnName, columnType) = columnNameExtra.split(":");
            columnNames.append(columnName);
            columnTypes[columnName] = columnType;
        return (columnNames, columnTypes);

    def loadComponents(self):
        self.netLogoWorld.empty();
        
        # get turtles from csv table and push them in NetLogo world
        turtleStream = self.textDemultiplexer.getStream(ImportNetLogoWorld.TYPE_TURTLES);
        turtlesReader = csv.DictReader(turtleStream);
        
        (columnNames, columnTypes) = self.splitParams(self.nParams);
        print("Additional node parameters to be imported from NetLogo world (with types): %s" %(self.nParams))
        print("Additional node parameters to be imported from NetLogo world (names): %s, (types): %s" %(columnNames, columnTypes.values()));
        for row in turtlesReader:
            additionalParams = TextDemultiplexer.newDict();
            for columnName in row.keys():
                #if( (0 > ImportNetLogoWorld.getElementIndexInList(columnName, ImportNetLogoWorld.PARAMS_TURTLES)) and \
                #   (0 > ImportNetLogoWorld.getElementIndexInList(columnName, ImportNetLogoWorld.PARAMS_TURTLES_FORBIDDEN))):
                if(0 <= ImportNetLogoWorld.getElementIndexInList(columnName, columnNames) ):
                    additionalParams[columnName] = row[columnName];
                
            self.netLogoWorld.addTurtleParams(row['who'], row['color'], row['heading'], row['xcor'], row['ycor'], row['shape'], row['label'], \
                                              row['label-color'], row['breed'], row['hidden?'], row['size'], row['pen-size'], row['pen-mode'], additionalParams, columnTypes);
        self.netLogoWorld.allTurtlesEntered();
        #print('Turtle 0 :%s' % (str(self.netLogoWorld.turtles[0])));

        # get links from csv table and push them in NetLogo world
        linksStream = self.textDemultiplexer.getStream(ImportNetLogoWorld.TYPE_LINKS);
        linksReader = csv.DictReader(linksStream);
        (columnNames, columnTypes) = self.splitParams(self.eParams);
        print("Additional edge parameters to be imported from NetLogo world (with types): %s" %(self.eParams))
        print("Additional edge parameters to be imported from NetLogo world (names): %s, (types): %s" %(columnNames, columnTypes.values()));
        for row in linksReader:
            additionalParams = TextDemultiplexer.newDict();
            for columnName in row.keys():
                if(0 <= ImportNetLogoWorld.getElementIndexInList(columnName, columnNames) ):
                    additionalParams[columnName] = row[columnName];
                
            self.netLogoWorld.addLinkParams(row['end1'], row['end2'], row['color'], row['label'], row['label-color'], row['hidden?'], row['breed'], \
                                              row['thickness'], row['shape'], row['tie-mode'], additionalParams, columnTypes);
        #print('Link 0 :%s' % (str(self.netLogoWorld.links[0])));
        #print('Link 0->0 :%s' % (str(self.netLogoWorld.linksMatrix[0][0])));
        #print('Link 0->1 :%s' % (str(self.netLogoWorld.linksMatrix[0][1])));
        
        # get patches from csv table and push them in NetLogo world
        patchesStream = self.textDemultiplexer.getStream(ImportNetLogoWorld.TYPE_PATCHES);
        patchesReader = csv.DictReader(patchesStream);
        for row in patchesReader:
            self.netLogoWorld.addPatchParams(row['pxcor'], row['pycor'], row['pcolor'], row['plabel'], row['plabel-color']);
        self.netLogoWorld.allPatchesEntered();
        #print('Patch 0 :%s' % (str(self.netLogoWorld.patches[0])));
        #print('Patch 0,0 :%s' % (str(self.netLogoWorld.patchesMatrix[0][0])));
        #print('Patch 50,-49 :%s' % (str(self.netLogoWorld.patchesMatrix[50][-49])));
        #print('Patch -50,49 :%s' % (str(self.netLogoWorld.patchesMatrix[-50][49])));
        #print('Patch -50,-50 :%s' % (str(self.netLogoWorld.patchesMatrix[-50][-50])));
        #print('Patch 50,50 :%s' % (str(self.netLogoWorld.patchesMatrix[50][50])));

    # =============
    # demuplexing netlogo world file that consists of few inner csv table
    # separated by empty line and then with the name of inner csv table (turtles, ...)
    # after the name we have csv table rows
    def demultiplexedLine(self, line, context):
        # if you check the netlogo-world csv export file you will see that before particular infile csv part there is an empty line 
        if(context['type'] == None):
            if(line == ('"'+ImportNetLogoWorld.TYPE_TURTLES+'"')):
                context['type'] = ImportNetLogoWorld.TYPE_TURTLES;
                print "Context switched to: %s" % (context['type'] );
                return None;
            elif(line == ('"'+ImportNetLogoWorld.TYPE_LINKS+'"')):
                context['type'] = ImportNetLogoWorld.TYPE_LINKS;
                print "Context switched to: %s" % (context['type'] );
                return None;
            elif(line == ('"'+ImportNetLogoWorld.TYPE_PATCHES+'"')):
                context['type'] = ImportNetLogoWorld.TYPE_PATCHES;
                print "Context switched to: %s" % (context['type'] );
                return None;
        if(line == '' and context['type']):
            context['type'] = None;
            #print "Context switched to: %s" % (context['type'] );
        
        # print line;
        #print "DemultiplexedLine finished..."
        # this directs demultiplexter which stream to put the line: stream name is equal to the value of context['type']
        return context['type'];
    def generateGraph(self, netLogoWorld, fileNameOut, nodeSizeMultiplyer, coordMultiplyer, edgeWeightMultiplyer, edgeWeightIgnore, nodeNamePrefix):
        self.netLogoWorld = netLogoWorld;
        self.fileNameOut = fileNameOut;
        print("Generating graph started ...");
        print("nodeSizeMultiplyer=%f, coordMultiplyer=%f, edgeWeightMultiplyer=%f, edgeWeightIgnore=%s, , nodeNamePrefix='%s'" \
              % (nodeSizeMultiplyer, coordMultiplyer, edgeWeightMultiplyer, edgeWeightIgnore, nodeNamePrefix))
        print "Igraph version %s" % (igraph.__version__);
        self.graph = igraph.Graph();

        # populating graph nodes from turtles
        self.graph.add_vertices(len(self.netLogoWorld.turtles));
        turtle = Turtle();
        i = 0;
        for turtle in self.netLogoWorld.turtles:
            #print("Turtle: who=%d, label=%s" %(turtle.who, turtle.label))
            # We cannot use id:
            #    self.graph.vs[i]['id'] = turtle.who;
            # it was necesarry to add name to be able to refer to names of edges when we are adding edges later
            # that is only possible way, since vertex ids (turtles who) are not necessarily starting from 0, and igrah insist on 0 and non-sparce vertices ids
            self.graph.vs[i]['name'] = str(turtle.who);
            self.graph.vs[i]['size'] = turtle.size * nodeSizeMultiplyer;
            rgbColor = NetLogoWorld.colorNetlotoToRgb(turtle.color);
            self.graph.vs[i]['r'] = rgbColor[0];
            self.graph.vs[i]['g'] = rgbColor[1];
            self.graph.vs[i]['b'] = rgbColor[2];
            self.graph.vs[i]['x'] = turtle.xcor * coordMultiplyer;
            self.graph.vs[i]['y'] = turtle.ycor * coordMultiplyer;
            if(turtle.label == None or turtle.label == ""):
                self.graph.vs[i]['label'] = "%s%d" % (nodeNamePrefix, turtle.who);
            else:
                self.graph.vs[i]['label'] = turtle.label;

            #self.graph.vs[i]['hophop'] = 'YESSS!!!';

            # adding additional non-recognized columns
            #print "keys:%s " %(turtle.additionalParams.keys());
            print(turtle.additionalParams.keys())
            for columnName in turtle.additionalParams.keys():
                columnType = turtle.columnTypes[columnName];
                print("columnName=%s, columnType=%s, value=%s" %(columnName, columnType, turtle.additionalParams[columnName]));
                
                if(columnType == "string"):
                    self.graph.vs[i][columnName] = str(turtle.additionalParams[columnName]);
                elif(columnType == "int"):
                    self.graph.vs[i][columnName] = int(turtle.additionalParams[columnName]);
                elif(columnType == "float"):
                    self.graph.vs[i][columnName] = float(turtle.additionalParams[columnName]);
            i =i+1;

        # populating edges nodes from links
        link = Link();
        i = 0;
        for link in self.netLogoWorld.links:            
            #print("link.end1 = %s, link.end2=%s" % (str(link.end1), str(link.end2)));
            #print self.graph;
            #print self.graph.get_edgelist();
            # we cannot add by integers
            #    self.graph.add_edges([(link.end1, link.end2)]);
            # because, that is recognized as igraph's vertex IDs, which do not need to match NetLogo turtle WHOs (if they do not start from 0)
            # There fore we need to refer by vertex names, and to do that we need to provide .add_edges() with strings instead of integers
            self.graph.add_edges([(str(link.end1), str(link.end2))]);
            self.graph.es[i]['Edge Id'] = link.end1 * 1000 + link.end2;
            if(link.label == None or link.label == ""):
                self.graph.es[i]['Edge Label'] = self.graph.es[i]['label'] = "%d-%d" % (link.end1, link.end2);
            else:
                self.graph.es[i]['Edge Label'] = self.graph.es[i]['label'] = turtle.label;
            if(not edgeWeightIgnore):
                self.graph.es[i]['weight'] = link.thickness*edgeWeightMultiplyer;
            
            print(link.additionalParams.keys())
            #print link.additionalParams.keys();
            for columnName in link.additionalParams.keys():
                columnType = link.columnTypes[columnName];
                print("columnName=%s, columnType=%s, value=%s" %(columnName, columnType, link.additionalParams[columnName]));
                
                if(columnType == "string"):
                    self.graph.es[i][columnName] = str(link.additionalParams[columnName]);
                elif(columnType == "int"):
                    self.graph.es[i][columnName] = int(link.additionalParams[columnName]);
                elif(columnType == "float"):
                    self.graph.es[i][columnName] = float(link.additionalParams[columnName]);
            i =i+1;

        igraph.summary(self.graph);
        self.graph.write_graphml(fileNameOut);
        print("Generating graph finished ...");