// // Scott Hale (Oxford Internet Institute)
// // Requires sigma.js and jquery to be loaded
// // based on parseGexf from Mathieu Jacomy @ Sciences Po M�dialab & WebAtlas


var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);

// Regular implementation for Chrome and other browsers
sigma.publicPrototype.parseJson = function(gzippedJsonPath, callback) {
  var sigmaInstance = this;
  
  // Use XMLHttpRequest for binary data
  var xhr = new XMLHttpRequest();
  xhr.open('GET', gzippedJsonPath, true);
  xhr.responseType = 'arraybuffer';
  
  xhr.onload = function() {
    if (xhr.status === 200) {
      try {
        // Decompress the gzipped data using pako
        var inflatedData = pako.inflate(new Uint8Array(xhr.response));
        
        // Convert binary data to string
        var jsonString = new TextDecoder('utf-8').decode(inflatedData);
        
        // Parse the JSON
        var jsonData = JSON.parse(jsonString);
        
        // Process nodes
        for (var i = 0; i < jsonData.nodes.length; i++) {
          var id = jsonData.nodes[i].id;
          sigmaInstance.addNode(id, jsonData.nodes[i]);
        }
        
        // Process edges
        for (var j = 0; j < jsonData.edges.length; j++) {
          var edgeNode = jsonData.edges[j];
          var source = edgeNode.source;
          var target = edgeNode.target;
          var label = edgeNode.label;
          var eid = edgeNode.id;
          
          sigmaInstance.addEdge(eid, source, target, edgeNode);
        }
        
        // Call the callback function if provided
        if (callback) {
          callback.call(sigmaInstance);
        }
      } catch (error) {
        console.error("Error processing gzipped JSON:", error);
      }
    } else {
      console.error("Error fetching gzipped JSON. Status:", xhr.status);
    }
  };
  
  xhr.onerror = function() {
    console.error("Network error while fetching gzipped JSON");
  };
  
  xhr.send();
};


// Create a new function specifically for loading gzipped data safely
// This avoids sigma initialization issues by loading data first
var loadGzippedGraphData = function(gzippedJsonPath, callback) {
  // Use XMLHttpRequest for binary data
  var xhr = new XMLHttpRequest();
  xhr.open('GET', gzippedJsonPath, true);
  xhr.responseType = 'arraybuffer';
  
  xhr.onload = function() {
    if (xhr.status === 200) {
      try {
        // Decompress the gzipped data using pako
        var inflatedData = pako.inflate(new Uint8Array(xhr.response));
        
        // Convert binary data to string
        var jsonString;
        try {
          jsonString = new TextDecoder('utf-8').decode(inflatedData);
        } catch (e) {
          // Fallback for older browsers
          jsonString = "";
          var array = inflatedData;
          var i = 0, len = array.length;
          var c, char2, char3;
          
          while (i < len) {
            c = array[i++];
            switch (c >> 4) {
              case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
                // 0xxxxxxx
                jsonString += String.fromCharCode(c);
                break;
              case 12: case 13:
                // 110x xxxx   10xx xxxx
                char2 = array[i++];
                jsonString += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
                break;
              case 14:
                // 1110 xxxx  10xx xxxx  10xx xxxx
                char2 = array[i++];
                char3 = array[i++];
                jsonString += String.fromCharCode(((c & 0x0F) << 12) |
                                               ((char2 & 0x3F) << 6) |
                                               ((char3 & 0x3F) << 0));
                break;
            }
          }
        }
        
        // Parse the JSON
        var jsonData = JSON.parse(jsonString);
        
        // Return the parsed data to the callback
        if (callback) {
          callback(jsonData);
        }
      } catch (error) {
        console.error("Error processing gzipped JSON:", error);
        if (callback) {
          callback(null, error);
        }
      }
    } else {
      console.error("Error fetching gzipped JSON. Status:", xhr.status);
      if (callback) {
        callback(null, new Error("HTTP status: " + xhr.status));
      }
    }
  };
  
  xhr.onerror = function() {
    console.error("Network error while fetching gzipped JSON");
    if (callback) {
      callback(null, new Error("Network error"));
    }
  };
  
  xhr.send();
};




// Safe initialization for Safari
function initSigmaWithGzippedData(containerId, gzippedJsonPath, options, callbackFn) {
  // Make options parameter optional
  if (typeof options === 'function') {
    callbackFn = options;
    options = {};
  }
  
  options = options || {};
  
  // For Safari, use a completely different approach
  if (isSafari) {
    // First, load the data
    loadGzippedGraphData(gzippedJsonPath, function(data, error) {
      if (error || !data) {
        console.error("Failed to load graph data:", error);
        return;
      }
      
      // Wait for DOM to be completely ready
      jQuery(document).ready(function() {
        // Make sure container is ready with dimensions
        var container = document.getElementById(containerId);
        if (!container) {
          console.error("Container not found:", containerId);
          return;
        }
        
        // Ensure container has dimensions
        if (!container.offsetWidth || !container.offsetHeight) {
          container.style.width = container.style.width || "100%";
          container.style.height = container.style.height || "500px";
          container.style.display = "block";
        }
        
        // Wait for next animation frame to ensure DOM updates
        requestAnimationFrame(function() {
          // Create settings with explicit container reference
          var sigmaSettings = Object.assign({}, options);
          
          // Wait a bit more for Safari
          setTimeout(function() {
            try {
              // Initialize sigma with empty graph first
              var sigmaInstance = new sigma(containerId);
              
              // Add nodes and edges manually
              for (var i = 0; i < data.nodes.length; i++) {
                var id = data.nodes[i].id;
                sigmaInstance.addNode(id, data.nodes[i]);
              }
              
              for (var j = 0; j < data.edges.length; j++) {
                var edgeNode = data.edges[j];
                var source = edgeNode.source;
                var target = edgeNode.target;
                var label = edgeNode.label || "";
                var eid = edgeNode.id;
                
                sigmaInstance.addEdge(eid, source, target, edgeNode);
              }
              
              // Refresh the graph
              sigmaInstance.refresh();
              
              // Call user callback if provided
              if (callbackFn) {
                callbackFn(sigmaInstance);
              }
            } catch (e) {
              console.error("Error initializing sigma:", e);
            }
          }, 300); // Longer delay for Safari
        });
      });
    });
  } else {
    // For Chrome and others, use a more standard approach
    jQuery(document).ready(function() {
      try {
        var sigmaInstance = new sigma(containerId);
        sigmaInstance.parseGzippedJson(gzippedJsonPath, function() {
          this.refresh();
          if (callbackFn) callbackFn(this);
        });
      } catch (e) {
        console.error("Error initializing sigma:", e);
      }
    });
  }
}