/* Copyright (c) 2008 Eden Li
 * See http://e.den.li/dict/license.txt
 */
var MARKS = {
  a: ["&#257;", "&#225;", "&#462;", "&#224;"],
  e: ["&#275;", "&#233;", "&#283;", "&#232;"],
  i: ["&#299;", "&#237;", "&#464;", "&#236;"],
  o: ["&#333;", "&#243;", "&#466;", "&#242;"],
  u: ["&#363;", "&#250;", "&#468;", "&#249;"],
  v: ["&#470;", "&#472;", "&#474;", "&#252;"]
};

jQuery.fn.pinyin = function(val) {
  return this.
    attr("class", "pin").
    html(
      val.
        toLowerCase().
        replace(/([a-z]*)([aeiou])([b-df-hj-np-tw-z]*)(\d+)/g,
          function(m, ini, vow, fin, tone) {
            return ini + (MARKS[vow][parseInt(tone) - 1] || vow) + fin;
          }
        )
    );
};

jQuery.fn.updateHistory = function() {
  var self = $(this);
  $.getJSON("/history",
    function(data) {
      $('.history-item').remove();
      $.each(data, function(i, item) {
        $('<li />').
          attr('class', 'history-item queryable').
          html(item.query).
          click(runQuery).appendTo(self);
      });
    }
  );
};

function runQuery() {
  $('#results').updateResults($(this).text());
}

jQuery.fn.updateResults = function(query) {
  var self = this;
  var page = 1;

  if (!query && self.attr("query")) {
    query = self.attr("query");
    page = parseInt(self.attr("page") || "0") + 1;
  }
  else {
    $('#query').val(query);
  }
  

  self.removeAttr("page");
  self.removeAttr("query");

  if (self.attr("updating") == "true") return self;

  self.attr("updating", true);

  if (page == 1) self.empty();

  self.append($('<dl />').attr("id", "loading").append(
    $('<dd />').text("loading...")
  ));

  var q = encodeURIComponent(query.replace(/ /g, '+'));
  $.getJSON(
    ["", "query", q, page].join("/"),
    function(data) {
      $('#loading').remove();
      if (page == 1) {
        $('#history').updateHistory();
        location.hash = query;
      }

      $('#stats').text(data.total + " results");

      $.each(data.results, function(i, result) {
        self.appendResult(result);
      });

      if (data.results.length == 0 && data.pages == 0) {
        self.append($('<p />').text("no results for '" + query + "'"));
      }
      else if (page >= data.pages) {
        self.append($('<dl />').append(
          $('<dd />').attr("class", "no-more").text("end of results")
        ));
      }
      else {
        self.attr("query", query);
        self.attr("page", page);
      }

      self.removeAttr("updating");
      updateStacking();
    }
  );
};

jQuery.fn.appendResult = function(result) {
  this.append(
    $('<dl />').
      append($('<dt />').html(result.sim)).
      append($('<dd />').pinyin(result.pin)).
      append($('<dd />').text(result.eng))
  );
};

function updateStacking() {
  /* #search-form          d1
   * padding      30px     d2
   * #results     window - d1 - d2 - d4 - d5 (d3)
   * padding      20px     d4
   * #cred                 d5
   */
  var d1 = $('#search-form').height();
  var d2 = 30;
  var d4 = 30;
  var d5 = $('#cred').height();
  var d3 = $(window).height() - (d1 + d2 + d4 + d5);

  $('#results').css({
    top: (d1 + d2) + "px",
    height: d3 + "px"
  });

  $('#cred').css({
    top: (d1 + d2 + d3) + "px"
  });

  var adjWidth;
  if ($(window).width() < 450) adjWidth = '90%';
  else if ($(window).width() < 900) adjWidth = '45%';
  else adjWidth = '30%';
  $('#results dl').css({width: adjWidth});
}

$(function() {
  $('#search-form').submit(function() {
    $("#results").updateResults($('#query').val());
    return false;
  });

  $(window).resize(updateStacking);
  updateStacking();

  $('#results').scroll(
    function() {
      if ((this.scrollTop / this.scrollHeight) > 0.80 && $(this).attr("query")) {
        $(this).updateResults();
      }
    }
  );

  $('#results').ajaxError(
    function(ev, req, opts, error) {
      $(this).removeAttr("updating");
      $(this).empty();
      $(this).append($('<p />').
        text(
          "Oops! The server's out to lunch." +
          "Try again in a few minutes, or " +
          "email me (edenli at gmail) if " +
          "this persists."));
    }
  );

  $('#history').updateHistory();

  if (/^#.+/.test(location.hash)) {
    var q = location.hash.replace(/^#/, '').replace('%20', ' ');
    $("#results").updateResults(q);
  }
});

