function sparql(endpoint, query, data) {
  netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');

  var client = new XMLHttpRequest();
  var req = endpoint+"?query="+escape(query)
  if (data) {
    req += "&default-graph-uri="+escape(data);
  }
  client.open('GET', req, false);
  client.send(null);
  var ress = client.responseXML.getElementsByTagName("result");
  var ret = new Array();
  for (var i=0; i < ress.length; i++) {
    var row = new Array();
    var res = ress.item(i);
    var binds = res.getElementsByTagName("binding");
    for (var j=0; j < binds.length; j++) {
      var bind = binds.item(j);
      var name = bind.getAttribute("name");
      var value = "";
	var uris = bind.getElementsByTagName("uri");
      if (uris.length == 1) {
	  var value = uris.item(0).firstChild.nodeValue;
      }
      row[name] = value;
    }
    ret.push(row);
  }

  return ret;
}

function go(debug) {
  document.body.style.cursor = "wait";
  var results = "";
  var endpoint = document.getElementById("endpoint").value;
  if (!endpoint) {
    alert("You need to provide a SPARQL endpoint");
  }
  var data_uri = document.getElementById("data").value;
  var prefix = "PREFIX : <http://plugin.org.uk/rdf/vote#> ";
  var q = prefix + "SELECT DISTINCT ?opt WHERE { ?x :for ?opt } ORDER BY ?opt";
  var res = sparql(endpoint, q, data_uri);
  if (debug) results += q + "\n";
  var options = new Array();
  for (var i in res) {
    options.push(res[i]['opt'])
  }
  var wins = new Array();
  var beatsorig = new Array();
  var beats = new Array();
  for (var i in options) {
    wins[options[i]] = new Array();
    beatsorig[options[i]] = new Array();
    beats[options[i]] = new Array();
    for (var j in options) {
      var a = options[i];
      var b = options[j];
      if (a == b) continue;
      q = prefix + "SELECT ?ra ?rb WHERE { ?voter :vote ?a . ?a :rank ?ra ; :for <"+a+"> . OPTIONAL { ?voter :vote ?b . ?b :rank ?rb ; :for <"+b+"> } FILTER( !BOUND(?rb) || ?ra < ?rb ) }";
      var winq = sparql(endpoint, q, data_uri);
      if (debug) results += q + "\n";
      wins[a][b] = winq.length;
    }
  }
  results += "@prefix : <http://plugin.org.uk/rdf/vote#> .\n";
  for (var i in options) {
    for (var j in options) {
      var a = options[i];
      var b = options[j];
      if (a == b) continue;
      if (wins[a][b] == wins[b][a]) {
	  results += "<"+a+"> :draws <"+b+"> .\n";
      } else if (wins[a][b] > wins[b][a]) {
      	  beatsorig[a][b] = 1;
      	  beats[a][b] = 1;
      }
    }
  }

  /* cull redundant transitive edges */
  for (var i in options) {
    for (var j in options) {
      for (var k in options) {
        var a = options[i];
        var b = options[j];
        var c = options[k];
	if (beatsorig[a][b] && beatsorig[b][c] && beatsorig[a][c]) {
	  beats[a][c] = 0;
	}
      }
    }
  }

  for (var i in options) {
    for (var j in options) {
      var a = options[i];
      var b = options[j];
      if (beats[a][b]) {
        results += "<"+a+"> :beats <"+b+"> .\n";
      }
    }
  }

  var out = document.getElementById("out");
  while (out.firstChild) {
    out.removeChild(out.firstChild);
  }
  out.appendChild(document.createTextNode(results));
  document.body.style.cursor = "default";
}

function example() {
  document.getElementById("endpoint").value = "http://sparql.org/sparql";
  document.getElementById("data").value = "http://plugin.org.uk/misc/condorcet.ttl";
  go(false);
}

