var rightBound = 110;
var fontBounds = [9, 20];

var links, sort;

/// setup and display

function printHTML() {
 document.write("<div id='menu'>");
 document.write("<h1><a href='http://kylemcdonald.net/'>new website: kylemcdonald.net</a></h1>");
 if(curProject != null)
  document.write("<h2 style='text-align: center;'><img src='../email.png' alt='email address' height=10 width=75></h2>");
 document.write("<div id='sort'></div><div id='links'></div></div>");
 links = document.getElementById("links");
 sort = document.getElementById("sort");
}

function printSorts() {
 var sortTypes = ["date", "name"];
 if(curProject != null) sortTypes.unshift("similarity");
 for(var i in sortTypes)
  sortTypes[i] = "<a href='javascript:sortLinks(" + sortTypes[i] + "Compare)'>" + sortTypes[i] + "</a>";
 print(sort, sortTypes.join(" | "));
}

function sortLinks(sortFunction) {
 projects.sort(sortFunction);
 if(toggleReverse(sortFunction))
  projects.reverse();
 var path = curProject == null ? "" : "../";
 clear(links);
 for(var i in projects) {
  var project = projects[i];

  var startDate = getDates(project)[0].valueOf();
  var leftOffset = map(startDate, dateBounds[0], dateBounds[1], 0, rightBound);

  var similarity = getSimilarity(curProject, project);
  var fontSize = map(similarity, similarityBounds[0], similarityBounds[1], fontBounds[1], fontBounds[0]);

  var text;

  if(project == curProject) {
    //continue;
    text = project[1];
    
  } else {
    text = "<a href='" + path + project[0] + "'>" + project[1] + "</a>";
  }

  print(links,
   "<div class='projectLink' style='left:" + leftOffset + "px; font-size:" + fontSize + "px'>" + text + "</div>");
 }
}

function print(obj, string) {
 obj.innerHTML += string;
}

function clear(obj) {
 obj.innerHTML = "";
}

function getProject(name) {
 for(var i in projects) {
  curName =  projects[i][1];
  if(curName == name.substring(0, curName.length))
   return projects[i];
 }
 return null;
}

/// dates

function getDates(project) {
 var splitDate = project[2].split('-');
 return [
  project[2] == "" ?
   new Date() : // empty means bidirectional ray
   new Date(splitDate[0]),
  splitDate.length != 2 ?
   new Date() : // one means directional ray
   new Date(splitDate[1])];
}

function getDateBounds() {
 var min = new Date(); // +inf (today)
 var max = new Date(0); // -inf (1969)
 for(var i in projects) {
  var cur = new Date(getDates(projects[i])[0]);
  if(cur < min)
   min = cur;
  if(cur > max)
   max = cur;
 }
 return [min.valueOf(), max.valueOf()];
}

/// similarity

function getTags(project) {
 return project[3].split(' ');
}

/*
See http://ncisgi.ncifcrf.gov/~lukeb/binclus.html
In a tag-based system, it doesn't make sense to talk about B00,
BI, or L. Thus, the good similarity metrics are TC, DCS, KS, CS,
S09, and S10. All difference metrics require L. Because we want
to sort, the similarity metric must also be symmetric.
*/
var similarities = {};
function getSimilarity(a, b) {
 if(a == null)
  return 0; // for main page
 if(!([a,b] in similarities)) {
  var i = getTags(a);
  var j = getTags(b);

  var Bi = i.length;
  var Bj = j.length;
  var BC = intersection(i,j).length;
  similarities[[a,b]] = BC / Math.sqrt(Bi * Bj); // Ochini
 }
 return similarities[[a,b]];
}

function getSimilarityBounds() {
 var min = 0;
 var max = Infinity;
 for(var i in projects) {
  if(projects[i] == curProject) continue;
  var cur = getSimilarity(curProject, projects[i]);
  if(cur > min)
   min = cur;
  if(cur < max)
   max = cur;
 }
 return [min, max];
}

/// sorting

var similarityReverse = false; // similarity is 1->0
var nameReverse = true;
var dateReverse = true;
function toggleReverse(sortFunction) {
 if(sortFunction == similarityCompare) {
  similarityReverse = similarityReverse ? false : true;
  return similarityReverse;
 }
 if(sortFunction == nameCompare) {
  nameReverse = nameReverse ? false : true;
  return nameReverse;
 }
 if(sortFunction == dateCompare) {
  dateReverse = dateReverse ? false : true;
  return dateReverse;
 }
}

function similarityCompare(a, b) {
 var sima = getSimilarity(curProject, a);
 var simb = getSimilarity(curProject, b);
 if(sima < simb) return -1;
 if(sima > simb) return +1;
 else return 0;
}

function nameCompare(a, b) {
 if(a[1] < b[1]) return -1;
 if(a[1] > b[1]) return +1;
 else return 0;
}

function dateCompare(a, b) {
 var aStart = getDates(a)[0];
 var bStart = getDates(b)[0];
 if(aStart < bStart) return -1;
 if(aStart > bStart) return +1;
 else return 0;
}

/// auxillary

function map(x, a, b, c, d) {
 return ((d - c) * (x - a) / (b - a)) + c;
}

function intersection(a, b) {
 var result = [];
 for(var i in a)
  for(var j in b)
   if(a[i] == b[j])
    result.push(a[i]);
 return result;
}
/// initial setup

var curProject = getProject(document.title);
var dateBounds = getDateBounds();
var similarityBounds = getSimilarityBounds();

printHTML();
printSorts();
sortLinks(dateCompare);