// Mathieu Jacomy @ Sciences Po Médialab & WebAtlas
// (requires sigma.js to be loaded)
sigma.publicPrototype.parseGexf = function(gexfPath) {
  // Load XML file:
  var gexfhttp, gexf;
  var sigmaInstance = this;
  gexfhttp = window.XMLHttpRequest ?
    new XMLHttpRequest() :
    new ActiveXObject('Microsoft.XMLHTTP');

  gexfhttp.overrideMimeType('text/xml');
  gexfhttp.open('GET', gexfPath, false);
  gexfhttp.send();
  gexf = gexfhttp.responseXML;

  var viz='http://www.gexf.net/1.2draft/viz'; // Vis namespace
  var i, j, k;

  // Parse Attributes
  // This is confusing, so I'll comment heavily
  var nodesAttributes = [];   // The list of attributes of the nodes of the graph that we build in json
  var nodesAttributesDict = {};
  var edgesAttributes = [];   // The list of attributes of the edges of the graph that we build in json
  var edgesAttributesDict = {};
  var attributesNodes = gexf.getElementsByTagName('attributes');  // In the gexf (that is an xml), the list of xml nodes 'attributes' (note the plural 's')

  for(i = 0; i<attributesNodes.length; i++){
    var attributesNode = attributesNodes[i];  // attributesNode is each xml node 'attributes' (plural)
    if(attributesNode.getAttribute('class') == 'node'){
      var attributeNodes = attributesNode.getElementsByTagName('attribute');  // The list of xml nodes 'attribute' (no 's')
      for(j = 0; j<attributeNodes.length; j++){
        var attributeNode = attributeNodes[j];  // Each xml node 'attribute'

        var id = attributeNode.getAttribute('id'),
          title = attributeNode.getAttribute('title'),
          type = attributeNode.getAttribute('type');

        var attribute = {id:id, title:title, type:type};
        nodesAttributes.push(attribute);
        nodesAttributesDict[id] = title

      }
    } else if(attributesNode.getAttribute('class') == 'edge'){
      var attributeNodes = attributesNode.getElementsByTagName('attribute');  // The list of xml nodes 'attribute' (no 's')
      for(j = 0; j<attributeNodes.length; j++){
        var attributeNode = attributeNodes[j];  // Each xml node 'attribute'
        
        var id = attributeNode.getAttribute('id'),
          title = attributeNode.getAttribute('title'),
          type = attributeNode.getAttribute('type');
          
        var attribute = {id:id, title:title, type:type};
        edgesAttributes.push(attribute);
        edgesAttributesDict[id] = title
        
      }
    }
  }
  
  var nodes = []; // The nodes of the graph
  var nodesNodes = gexf.getElementsByTagName('nodes') // The list of xml nodes 'nodes' (plural)
  
  for(i=0; i<nodesNodes.length; i++){
    var nodesNode = nodesNodes[i];  // Each xml node 'nodes' (plural)
    var nodeNodes = nodesNode.getElementsByTagName('node'); // The list of xml nodes 'node' (no 's')

    for(j=0; j<nodeNodes.length; j++){
      var nodeNode = nodeNodes[j];  // Each xml node 'node' (no 's')
      
      window.NODE = nodeNode;

      var id = nodeNode.getAttribute('id');
      var label = nodeNode.getAttribute('label') || id;
      
      //viz
      var size = 1;
      var x = 100 - 200*Math.random();
      var y = 100 - 200*Math.random();
      var color;
      
      var sizeNodes = nodeNode.getElementsByTagName('size');
      sizeNodes = sizeNodes.length ? 
                  sizeNodes : 
                  nodeNode.getElementsByTagNameNS('*','size');
      if(sizeNodes.length>0){
        sizeNode = sizeNodes[0];
        size = parseFloat(sizeNode.getAttribute('value'));
      }

      var positionNodes = nodeNode.getElementsByTagName('position');
      positionNodes = positionNodes.length ? 
                      positionNodes : 
                      nodeNode.getElementsByTagNameNS('*','position');
      if(positionNodes.length>0){
        var positionNode = positionNodes[0];
        x = parseFloat(positionNode.getAttribute('x'));
        y = parseFloat(positionNode.getAttribute('y'));
      }

      var colorNodes = nodeNode.getElementsByTagName('color');
      colorNodes = colorNodes.length ? 
                   colorNodes : 
                   nodeNode.getElementsByTagNameNS('*','color');
      if(colorNodes.length>0){
        colorNode = colorNodes[0];
        color = '#'+sigma.tools.rgbToHex(parseFloat(colorNode.getAttribute('r')),
                                         parseFloat(colorNode.getAttribute('g')),
                                         parseFloat(colorNode.getAttribute('b')));
      }
      
      var colorsProcessed = {};
if (nodeJSON.colors) {
  for (var key in nodeJSON.colors) {
    if (nodeJSON.colors.hasOwnProperty(key)) {
      // Get the rgb string for this property, e.g., "rgb(198,116,255)"
      var rgbStr = nodeJSON.colors[key];
      // Remove "rgb(" and ")" then split by comma to extract r, g, b values
      var rgbArr = rgbStr.replace(/rgb\(|\)/g, '').split(',');
      var r_val = parseInt(rgbArr[0].trim(), 10);
      var g_val = parseInt(rgbArr[1].trim(), 10);
      var b_val = parseInt(rgbArr[2].trim(), 10);
      // Convert to hex and store under the corresponding key
      colorsProcessed[key] = '#' + sigma.tools.rgbToHex(r_val, g_val, b_val);
    }
  }
}
      
      // Create Node
      var node = {label:label, size:size, x:x, y:y, attributes:{}, color:color,   colors: colorsProcessed};  // The graph node
      
      // Attribute values
      var attvalueNodes = nodeNode.getElementsByTagName('attvalue');
      for(k=0; k<attvalueNodes.length; k++){
        var attvalueNode = attvalueNodes[k];
        var attr = attvalueNode.getAttribute('for');
        var val = attvalueNode.getAttribute('value');
        node.attributes[nodesAttributesDict[attr]] = val;
      }

      sigmaInstance.addNode(id,node);
    }
  }

  var edges = [];
  var edgeId = 0;
  var edgesNodes = gexf.getElementsByTagName('edges');
  for(i=0; i<edgesNodes.length; i++){
    var edgesNode = edgesNodes[i];
    var edgeNodes = edgesNode.getElementsByTagName('edge');
    for(j=0; j<edgeNodes.length; j++){
      var edgeNode = edgeNodes[j];
      var source = edgeNode.getAttribute('source');
      var target = edgeNode.getAttribute('target');
      var label = edgeNode.getAttribute('label');
      var edge = {
        id:         j,
        sourceID:   source,
        targetID:   target,
        label:      label,
        attributes: {}
      };

      var attrs = edgeNode.attributes;
      for(var i=0;i<attrs.length;i++) {
          var n = attrs[i].name;
          if(n == 'source' || n =='target' || n=='label')
              continue;
          edge.attributes[n]=attrs[i].value;
      }

      var weight = edgeNode.getAttribute('weight');
      if(weight!=undefined){
        edge['weight'] = weight;
      }

      var attvalueNodes = edgeNode.getElementsByTagName('attvalue');
      for(k=0; k<attvalueNodes.length; k++){
        var attvalueNode = attvalueNodes[k];
        var attr = attvalueNode.getAttribute('for');
        var val = attvalueNode.getAttribute('value');
        edge.attributes[edgesAttributesDict[attr]] = val;
      }

      sigmaInstance.addEdge(edgeId++,source,target,edge);
    }
  }
};