function CONST() {};
CONST.USER_PRESSED_SEARCH = false;
CONST.PARAM = '';
CONST.USE_LOG = false;

CONST.MAX_COMPARISONS = 4;
CONST.INFINITY = 99999;

CONST.HEART = "<img class=icon src=pix/heart.gif>";
CONST.THUMBSDOWN = "<img class=icon src=pix/thumbs-down.gif>";
CONST.AWARD = "<img class=icon src=pix/award_icon.gif>";

function aos() {};

aos.onloadHandler = function() {
  aos.PopupInfo.init();
  aos.prefillComparisonMenu();
  aos.Ads.fillSearchSelections();
  aos.submitResults();
  //aos._testSubmit();  // for debugging

  // test pop up
  //aos.PopupInfo.fieldIdx = 0;
  //aos.PopupInfo.showResults({compared:"[hoho,haha]",synonym:"baba"});
};

// create a self referencing link based on the fields
aos.genUrlLink = function() {
  var url = window.location.href;
  url = url.replace(/\?.*/, "");
  var paramList = Array();
  var idx = 0;
  for (var i = 0; i < CONST.MAX_COMPARISONS; i++) {
    var field = document.getElementById("comparison" + i);
    if (field != null && field.value != null && field.value != "") {
      var value = field.value;
      value = value.replace(/\s+,/, ",").replace(/,\s+/, ",");
      value = value.replace(/^\s+/, "").replace(/\s+$/, "");
      if (value != "") {
        paramList.push("wd" + (idx++) + "=" + encodeURI(value));
      }
    }
  }
  return url + "?" + paramList.join('&');
};

aos.resetFields = function() {
  for (var i = 0; i < CONST.MAX_COMPARISONS; i++) {
    var field = document.getElementById("comparison" + i);
    if (field != null) field.value = '';
  }
  document.getElementById("comparison0").focus();
};

aos.prefillComparisonMenu = function() {
  var entry = document.getElementById("comparison0");
  if (entry == null) {
    var words = Array();

    for (var i = 0; i < CONST.MAX_COMPARISONS; i++) {
      var word = gup("wd" + i);
      if (word != null && word != "") {
        words.push(decodeURI(word));
      }
    }
    if (words.length == 0) words = ['apples', 'oranges'];

    for (var i = 0; i < words.length; i++) {
      aos.appendComparisonTextField(i, words[i]);
    }
    for (var i = words.length; i < CONST.MAX_COMPARISONS; i++) {
      aos.appendComparisonTextField(i, '');
    }
  }
};

// get parameter from URL
// http://www.netlobo.com/url_query_string_javascript.html
function gup(name) {
  name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
  var regexS = "[\\?&\#]"+name+"=([^&#]*)";
  var regex = new RegExp( regexS );
  var results = regex.exec( window.location.href );
  if( results == null )
    return "";
  else
    return results[1];
}

aos.appendComparisonTextField = function(idx, defaultVal) {
  var text = document.getElementById("comparison" + idx);
  if (text != null) return;
  
  var div = document.getElementById("comparisons");
  text = document.createElement("input");
  text.setAttribute("type", "text");
  text.setAttribute("id", "comparison" + idx);
  text.setAttribute("name", "comparison" + idx);
  text.setAttribute("value", defaultVal);

  text.setAttribute("onkeyup", "aos.PopupInfo.suggest(" + idx + ", 1800);");
  text.setAttribute("onclick", "aos.PopupInfo.suggest(" + idx + ", 50);");
  //text.setAttribute("onfocus", 
  //                  "aos.PopupInfo.suggest(" + idx + ", 100);");
  text.setAttribute("onchange", "aos.Ads.fillSearchSelections();");
  text.setAttribute("onblur", "aos.PopupInfo.hide(" + idx + ");");
  div.appendChild(text);
  div.appendChild(document.createElement("br"));
};

aos.submitResults = function() {
  aos.hideDiv("summaryTable");
  aos.showDiv("wait");

  // get parameters
  var paramArray = Array();
  var idx = 0;
  for (var i = 0; i < CONST.MAX_COMPARISONS; i++) {
    var comparisonField = document.getElementById("comparison" + i);
    if (comparisonField != null && comparisonField.value != "") {
      paramArray.push("wd" + (idx++) + "=" + 
                      encodeURI(comparisonField.value));
    }
  }

  CONST.PARAM = paramArray.join('&');
  // Note: we no longer request 'context' for ad (doesn't work)

  if (CONST.PARAM == "") {
    document.getElementById("summaryContent").innerHTML = "";
    document.getElementById("footerContent").innerHTML = "";
    aos.hideDiv("wait");
    aos.showDiv("summaryTable");
    alert("Please enter item(s)");
    return;
  }

  var url = './submit.php';
  //alert("Getting URL " + url + "?" + CONST.PARAM);
  var myAjax = new Ajax.Request(
    url,
    {
      method: 'get',
      parameters: CONST.PARAM,
      onSuccess: aos.getResults,
      onFailure: aos.failedResults
    });
};

aos.getResults = function(originalRequest) {
  if (CONST.USER_PRESSED_SEARCH && CONST.PARAM != '') {
    var loc = window.location.href + '?';
    loc = loc.replace(/\?.*/, "?" + CONST.PARAM);
    window.location.replace(loc);
    //window.location.replace("./?Hello world");
    //window.location.href.replace(/\?.*/, "?hey");
    //window.location.hash="hello";
    //parent.location.hash = 'hello2';
    return;
  }

  aos.hideDiv("wait");
  aos.showDiv("summaryTable");

  // object-fy the JSON payload
  var wordList, info, context, footerContent;
  try {
    var myVar = eval('(' + originalRequest.responseText + ')');
    wordList = myVar.words;  // list of words
    info = myVar.infoArray;  // love/hate/ration information
    footerContent = myVar.footerContent;  // misc notes on the bottom
    //context = myVar.context;  // context of search for ad purpose
  } catch (e) { }
  if (wordList == null && info == null) {
    // fatal error
    var div = document.getElementById("summaryContent");
    div.innerHTML = "Fatal error, please come back later.<br/><br/>" +
      "<tt>" + originalRequest.responseText + "</tt>";
    throw("Unknown results");
  }
  
  // debugging only
  var summaryContent = document.getElementById("summaryContent");
  summaryContent.innerHTML = '';
  for (var i = 0; i < wordList.length; i++) {
    summaryContent.innerHTML += "Word " + i + " = " + wordList[i] + "<br/>";
  }
  //alert("I have " + originalRequest.responseText);

  // ------- setup critical data for graph and summary
  // generate ticks
  var xTicks = new Array();
  var totalCountArray = new Array();
  var loveArray = new Array();
  var hateArray = new Array();
  var ratioArray = new Array();

  //alert("wordList " + wordList);

  for (var i = 0; i < wordList.length; i++) {
    var word = wordList[i];
    var array = Object();
    array.v = i;
    array.label = word;
    xTicks[i] = array;

    var love = info[word] ? parseInt(info[word].love) : 0;
    var hate = info[word] ? parseInt(info[word].hate) : 0;
    var ratio = info[word] ? parseFloat(info[word].ratio) : 0;
    totalCountArray.push([i, love + hate]);
    loveArray.push([i, love]);
    hateArray.push([i, hate]);
    ratioArray.push([i, ratio]);
  }

  if (footerContent != null) {
    document.getElementById("footerContent").innerHTML += footerContent;
  }
  //alert("YO");
  aos.generateSummary(totalCountArray, loveArray, hateArray, 
                      ratioArray, xTicks);

  aos.renderGraphs(totalCountArray, loveArray, hateArray, 
                   ratioArray, xTicks);

};

aos.generateSummary = function(totalCountArray, 
                               loveArray, hateArray, ratioArray,
                               xTicks) {
  var div = document.getElementById("summaryContent");
  


  // generate a table
  var label = Array();
  var winnerIdx;
  var winnerLoveRatio = -1;
  var ratioList = Array();  // list of ratios, used for sorting
  var nameList = Object();  // ratio to name
  var nameToRatio = Object();  // associative array from name to ratio
  var lineList = Object();  // ratio to HTML line
  for (var i = 0; i < xTicks.length; i++) {
    var name = xTicks[i].label;
    label[i] = name;
    var ratio = ratioArray[i][1];
    ratio = parseInt(ratio * 1000) / 1000;
    if (ratio > winnerLoveRatio) {
      winnerIdx = i;
      winnerLoveRatio = ratio;
    }
    var line = "<tr><td>" + name + "_award_</td><td>" +
      totalCountArray[i][1] + "</td><td>" +
      loveArray[i][1] + "</td><td>" +
      hateArray[i][1] + "</td>" +
      "<td valign=center>" +
      aos.numberGuard(ratio) + 
      (ratio > 5 ? CONST.HEART : "") +
      (ratio > 50 ? CONST.HEART : "") +
      (ratio > 100 ? CONST.HEART : "") +
      (ratio > 500 ? CONST.HEART : "") +
      (ratio < 0.75 ? CONST.THUMBSDOWN : "") +
      (ratio < 0.25 ? CONST.THUMBSDOWN : "") +
      (ratio < 0.05 ? CONST.THUMBSDOWN : "") +
      (ratio < 0.01 ? CONST.THUMBSDOWN : "") +
      "</td></tr>\n";
    if (lineList[ratio] == null) lineList[ratio] = Array();
    lineList[ratio].push(line);

    nameToRatio[name] = ratio; 
    if (nameList[ratio] == null) nameList[ratio] = Array();
    nameList[ratio].push(name);

    ratioList.push(ratio);  // list of ratios for sorting later
  }
  ratioList.sort(compareIntegers).reverse();

  // generate HTML and create incrementalNameList
  var html = "<table border=1 align=left class=summaryBox>" +
    "<tr><th>Name</th><th><font color=blue>References</font></th>" +
    "<th><font color=green>Love</font></th>" +
    "<th><font color=red>Hate</font></th>" +
    "<th><font color=purple>Love/Hate Ratio</font></th>\n";
  var incrementalNameList = Array();
  var incrementalRatioList = Array();
  for (var i = 0; i < ratioList.length; i++) {
    var ratio = ratioList[i];
    var lines = lineList[ratio];
    var names = nameList[ratio];
    for (var j = 0; j < lines.length; j++) {
      var line = lines[j];
      if (ratioList.length > 1 && i == 0) {
        // give award!
        line = line.replace("_award_", CONST.AWARD);
      } else {
        line = line.replace("_award_", "");
      }
      html += line;

      var name = names[j];
      incrementalNameList.push(name);
      incrementalRatioList.push(ratio);
    }
    if (lines.length > 1) {
      i += lines.length - 1;
    }
  }
  html += "</tr></table>";

  // ordered list generation
  var orderedList = "";  // rough approximation
  var orderedList2 = "";  // rounded off approximation (w/ int constants)
  var orderedList3 = "";  // precise ordered list (= operator)
  for (var i = incrementalNameList.length - 1; i >= 0; i--) {
    var name = incrementalNameList[i];
    var ratio = incrementalRatioList[i];
    var nextRatio = (i > 0 ? incrementalRatioList[i - 1] : ratio);;
    {
      var multiplier = nextRatio / ratio;
      orderedList += name;
      orderedList2 += " (" + parseInt(multiplier) + "*" + name + ")";
      orderedList3 += " (" + 
        (parseInt((winnerLoveRatio/ratio)*100)/100) + 
        "*" + name + ")";

      if (i > 0) {
        if (multiplier == 1) {
          orderedList += " = ";
          orderedList2 += " = ";
          orderedList3 += " = ";
        } else {
          orderedList += " &lt; ";
          orderedList2 += " &lt; ";
          orderedList3 += " &lt= ";
        }
      }
    }
  }

  html += "This site counts the number of web pages that reference " +
    "&quot;I love <i>subject</i>&quot; (love-items) and " +
    "&quot;I hate <i>subject</i>&quot; (hate-items). " +
    "Search terms are surrounded by quotes to ensure exact searches. " +
    "The <i>love/hate ratio</i> is calculated by the number of " +
    "love-items over hate-items. " +
    "A ratio of 1 means for each occurrence of love-item, there is " +
    "an exact occurrence of hate-item. " +
    "The higher the love/hate ratio, the more liked the search item is. " +
    "Likewise, the lower the love/hate ratio (below 1), the lower ranked " +
    "the item is.<br/><br/>";
  
  if (ratioList.length > 1) {
    html += "In your search for " +
      label.join(' and ') + 
      ", '" + label[winnerIdx] + 
      "' has the highest love/hate ratio of " +
      aos.numberGuard(winnerLoveRatio) + "" +
      (winnerLoveRatio == CONST.INFINITY ? "<sup>1</sup>" : "") + 
      "</b>. " +
      "In another word, there are " + aos.numberGuard(winnerLoveRatio) + 
      " love-items found for every hate-item. ";
    html += "Mathematically speaking, the love/hate ratio " +
      "ordered set is as follows: " +
      "<span style='background-color:yellow';>" +
      "<b>" + orderedList + "</b></span><sup>2</sup>. ";
  }
  var link = aos.genUrlLink();
  var visLink = link;
  if (visLink.length > 80) {
    visLink = visLink.substr(0, 75) + "<i>...</i>";
  }
  html += " Here is a direct link " +
    "to use to share with your friends: " +
    "<a href=\"" + link + "\">" + visLink + "</a> ";

  div.innerHTML = html;

  // footer
  html = '';
  if (winnerLoveRatio == CONST.INFINITY) {
    html += "<sup>1</sup>This simply means " +
      "there is no reference to " + 
      "&quot;I hate " + label[winnerIdx] + ".&quot;<br/>\n";
  }
  if (ratioList.length > 1) {
    html += "<sup>2</sup>";
    html += "More precisely, it is " +
      "<span><tt>" +
      orderedList2 + "</tt></span>. ";
    html += "Even more precisely, it is " +
      "<span><tt>" +
      orderedList3 + "</tt></span>.<br/>\n";
  }
  if (html != '') {
    html = "<br/><br/><hr width=33%/><font size=-1>" + html + "</font>";
  }
  document.getElementById("footerContent").innerHTML += html;
};

aos.renderGraphs = function(totalCountArray, 
                            loveArray, hateArray, ratioArray,
                            xTicks) {
  var options = {
    "IECanvasHTC": "plotkit/iecanvas.htc",
    "colorScheme": PlotKit.Base.palette(PlotKit.Base.baseColors()[0]), 
    //"colorScheme": colors,
    "padding": {left: 10, right: 10, top: 10, bottom: 30},
    "xTicks": xTicks,
    "drawYAxis": false,
    "pieRadius": 0.35
  };

  // clear up graph
  document.getElementById("canvaspie").innerHTML = '';
  document.getElementById("canvasbar1").innerHTML = '';
  document.getElementById("canvasbar2").innerHTML = '';

  var browser = BrowserDetect.browser;
  if (browser == 'Explorer') {
    document.getElementById("canvaspie").innerHTML = 
      document.getElementById("canvasbar1").innerHTML =
      document.getElementById("canvasbar2").innerHTML =
      ('<table border=0><tr><td bgcolor=pink><font size=-1>' +
       'NOTE: Internet Explorer may not display graph here correctly. ' +
       'This site is tuned for good browsers like <b>Firefox</b>.' +
       '</font></td></tr></table>');
  } else if (browser != 'Firefox') {
    document.getElementById("canvaspie").innerHTML = 
      document.getElementById("canvasbar1").innerHTML =
      document.getElementById("canvasbar2").innerHTML =
      ('<table border=0><tr><td bgcolor=pink><font size=-2>' +
       'NOTE: You are using ' + browser + '. That is fine. Note that ' +
       'This site is fine-tuned for good browsers like <b>Firefox</b>. ' +
       'Dynamic graph here may not display correctly, if at all.' +
       '</font></td></tr></table>');
  }

  var hasCanvas = CanvasRenderer.isSupported();
  if (hasCanvas) {
    var pie = new EasyPlot("pie", options, $('canvaspie'), 
      [totalCountArray]);

    //options.colorScheme = PlotKit.Base.palette(PlotKit.Base.baseColors()[4]); 

    // Love hate has new colors
    var colors = [
      new MochiKit.Color.Color(0.00, 0.80, 0.05),
      new MochiKit.Color.Color(0.70, 0.00, 0.05),
    ];
    options.colorScheme = colors;
    var bar = new EasyPlot("bar", options, $('canvasbar1'), 
      [loveArray, hateArray]);

    // use log for clarity
    var displayRatioArray = Array();
    for (var i = 0; i < ratioArray.length; i++) {
      var val = CONST.USE_LOG ? 
        Math.log((ratioArray[i][1]+1)*2) :
        ratioArray[i][1];
      displayRatioArray.push([i, val]);
    }
    var colors = [
      new MochiKit.Color.Color(0.80, 0.00, 0.80),
    ];
    options.colorScheme = colors;
    var bar = new EasyPlot("bar", options, $('canvasbar2'), 
      [displayRatioArray]);
  } else {
    document.getElementById("graph").innerHTML =
      "Sorry your browser does not display graphs.";
  }
};

aos._testSubmit = function() {
  var json = Object;
  json.responseText = '{"words":["civic"],"infoArray":{"civic":{"love":"4670","hate":"230","ratio":"20.3043"}},"footerContent":"Yo this is footer"}';
  aos.getResults(json);
  return;

  var totalCountArray = [[0,5], [1,8]];
  var loveArray = [[0,5], [1,8]];
  var hateArray = [[0,8], [1,88]];
  var ratioArray = [[0,15], [1,8]];
  var xTicks = [{v:0, label:'hello'}, {v:1, label:'world'}];
  aos.renderGraphs(totalCountArray,
                   loveArray, hateArray, ratioArray,
                   xTicks);
  aos.generateSummary(totalCountArray,
                      loveArray, hateArray, ratioArray,
                      xTicks);

};

aos.failedResults = function(originalRequest) {
  aos.showDiv("summaryTable");
  document.getElementById("summaryContent").innerHTML = 
    "Something went wrong..." + originalRequest.responseText + 
    " Please try again later, or use a different browser";

  aos.hideDiv("wait");
};

// --------------- Ads
aos.Ads = function() { };
aos.Ads.fillSearchSelections = function() {
  var hateSelections = Array();
  var loveSelections = Array();
  var hateHTML = '';
  var loveHTML = '';
  for (var i = 0; i < CONST.MAX_COMPARISONS; i++) {
    var div = document.getElementById("comparison" + i);
    if (div != null && div.value != '') {
      var term = 'I love ' + div.value;
      loveSelections.push(term);
      loveHTML += '<span onclick="aos.Ads.fillSearch(\'' +
        term + '\');" style="cursor:pointer;">"' + term + '"</span> ';

      var term = 'I hate ' + div.value;
      hateSelections.push(term);
      hateHTML += '<span onclick="aos.Ads.fillSearch(\'' +
        term + '\');" style="cursor:pointer;">"' + term + '"</span> ';
    }
  }
  var optionDiv = document.getElementById("googleSearchSelections");
  optionDiv.innerHTML = 'Experiment with these: ';
  optionDiv.innerHTML += '<font color=green>' + loveHTML + '</font>' +
    '<font color=red>' + hateHTML + '</font>';

  // fill the search box
  aos.Ads.fillSearch(loveSelections[Math.floor(Math.random() * 
                                               loveSelections.length)]);
};
aos.Ads.fillSearch = function(word) {
  var searchDiv = document.getElementById("sbi");
  searchDiv.value = '"' + word + '"';
}


// --------------- Utilities
aos.hideDiv = function(name) {
  var div = document.getElementById(name);
  if (div == null) throw("Cannot find " + name);
  div.style.display = 'none';
};
aos.showDiv = function(name) {
  var div = document.getElementById(name);
  if (div == null) throw("Cannot find " + name);
  div.style.display = '';
};
aos.numberGuard = function(i) {
  return (i == CONST.INFINITY ? "infinity" : i);
};
function compareIntegers(num1, num2) {
  if (num1 < num2) {
    return -1;
  } else if (num1 > num2) {
    return 1;
  } else {
    return 0;
  }
};

// from: http://www.quirksmode.org/js/detect.html
var BrowserDetect = {
  init: function () {
    this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
    this.version = this.searchVersion(navigator.userAgent)
      || this.searchVersion(navigator.appVersion)
      || "an unknown version";
    this.OS = this.searchString(this.dataOS) || "an unknown OS";
  },
  searchString: function (data) {
    for (var i=0;i<data.length;i++)	{
      var dataString = data[i].string;
      var dataProp = data[i].prop;
      this.versionSearchString = data[i].versionSearch || data[i].identity;
      if (dataString) {
	if (dataString.indexOf(data[i].subString) != -1)
	  return data[i].identity;
      }
      else if (dataProp)
	return data[i].identity;
    }
  },
  searchVersion: function (dataString) {
    var index = dataString.indexOf(this.versionSearchString);
    if (index == -1) return;
    return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
  },
  dataBrowser: [
    { 	string: navigator.userAgent,
	subString: "OmniWeb",
	versionSearch: "OmniWeb/",
	identity: "OmniWeb"
    },
    {
      string: navigator.vendor,
      subString: "Apple",
      identity: "Safari"
    },
    {
      prop: window.opera,
      identity: "Opera"
    },
    {
      string: navigator.vendor,
      subString: "iCab",
      identity: "iCab"
    },
    {
      string: navigator.vendor,
      subString: "KDE",
      identity: "Konqueror"
    },
    {
      string: navigator.userAgent,
      subString: "Firefox",
      identity: "Firefox"
    },
    {
      string: navigator.vendor,
      subString: "Camino",
      identity: "Camino"
    },
    {		// for newer Netscapes (6+)
      string: navigator.userAgent,
      subString: "Netscape",
      identity: "Netscape"
    },
    {
      string: navigator.userAgent,
      subString: "MSIE",
      identity: "Explorer",
      versionSearch: "MSIE"
    },
    {
      string: navigator.userAgent,
      subString: "Gecko",
      identity: "Mozilla",
      versionSearch: "rv"
    },
    { 		// for older Netscapes (4-)
      string: navigator.userAgent,
      subString: "Mozilla",
      identity: "Netscape",
      versionSearch: "Mozilla"
    }
  ],
  dataOS : [
    {
      string: navigator.platform,
      subString: "Win",
      identity: "Windows"
    },
    {
      string: navigator.platform,
      subString: "Mac",
      identity: "Mac"
    },
    {
      string: navigator.platform,
      subString: "Linux",
      identity: "Linux"
    }
  ]

};
BrowserDetect.init();

