var active_image = null;
var images = new Array();
var scores = new Array();  // item_id => score
var boxes = new Array();   // item_id => box div
var score_sorted = new Array(); // ii => item_id, desc
var age_sorted = new Array();   // ii => item_id, oldest first
var want_more = 0;
var ajax_pending = new Array();
var ajax_last = 0;

var stored_template = new Template('<div id="saved_#{id}" style="float: left; display: none;"><img src="#{micro}" onclick="showinfo(\'#{full}\', \'#{info}\');" /></span>');
var model_tag_template = new Template('<span class="model_tag" id="model_#{name}">#{title}</span><br />');

Event.observe(window, 'load', function() {
  for (var ii = 0; ii < 49; ii++) {
    scores[ii] = 0;
    boxes[ii] = $('box_' + ii);
    score_sorted[ii] = ii;
    age_sorted[ii] = ii;
  }

  new PeriodicalExecuter(function (pe) {
    // Look for invisibles that have a non--Infinity score
    for (var ii = 0; ii < 49; ii++) {
      if (score_sorted[ii] == undefined || boxes[score_sorted[ii]] == null) {
        score_sorted.splice(ii, 1);
        return;
      }
      if (scores[score_sorted[ii]] != -Infinity)
        if (!boxes[score_sorted[ii]].childElements().last().visible()) {
          Rescore(score_sorted[ii], -Infinity);
	  DoRequest({}, 1);
          return;
        }
    }
  }, 1.0);
});

function activate(thumbsup, thumbsdown) {
  if (active_image && active_image.thumbsup == thumbsup)
    return;
  if (active_image && document.getElementById(active_image.thumbsup) != null) {
    active_image.thumbs_hide();
  }
  if (images[thumbsup])
    active_image = images[thumbsup];
  else
    active_image = images[thumbsup] = new ThumbedImage(thumbsup, thumbsdown);
  active_image.thumbs_show();
}

function ThumbedImage(thumbsup, thumbsdown) {
  this.thumbsup = thumbsup;
  this.thumbsdown = thumbsdown;
  this.active = false;

  this.thumbs_show = function() {
    var doit = function(obj) {
      if ($(thumbsup).visible())
        return;
      obj.active = true;
      new Effect.SlideDown(thumbsup, {duration: .5});
      if (thumbsdown) {
        new Effect.SlideUp("x" + thumbsdown, {duration: .5});
        new Effect.SlideDown(thumbsdown, {duration: .5});
      }
      setTimeout(function () {
	// make sure we still exist
	if (document.getElementById(thumbsup) == null)
          return;
        var action = obj.active;
        obj.active = false;
        if (action && action != true) {
          action(obj);
        }
      }, 700);
    }
    if (this.active) {
      this.active = doit;
    } else {
      doit(this);
    }
  }

  this.thumbs_hide = function() {
    var doit = function(obj) {
      if (!$(thumbsup).visible())
        return;
      obj.active = true;
      new Effect.SlideUp(thumbsup, {duration: .5});
      if (thumbsdown) {
        new Effect.SlideDown("x" + thumbsdown, {duration: .5});
        new Effect.SlideUp(thumbsdown, {duration: .5});
      }
      setTimeout(function () {
	// make sure we still exist
	if (document.getElementById(thumbsup) == null)
          return;
        var action = obj.active;
        obj.active = false;
        if (action && action != true) {
          action(obj);
        }
      }, 700);
    }
    if (this.active) {
      this.active = doit;
    } else {
      doit(this);
    }
  }
}

function showinfo(url, info) {
  $('showinfo_held').innerHTML = '<center><img style="border: 2px solid #000000;" src="' + url + '" /><br/><a href="' + info + '" style="background-color: #ffffff">Go to the flickr page.</a></center>';
  $('showinfo').show();
}

function ThumbUp(div, id, micro, full, info) {
  DoRequest({id: id, thumb: 'up'}, 8);

  new Effect.SlideUp(div);
  Rescore(id, -Infinity);

  $('saved').insert({bottom: stored_template.evaluate({id: id, micro: micro, full: full, info: info})});
  new Effect.SlideDown("saved_" + id);
}

function ThumbDown(div, id, micro, full, info) {
  DoRequest({id: id, thumb: 'down'}, 8);

  new Effect.SlideUp(div);
  Rescore(id, -Infinity);

  $('dropped').insert({bottom: stored_template.evaluate({id: id, micro: micro, full: full, info: info})});
  new Effect.SlideDown("saved_" + id);
}

function DoRequest(params, get_more) {
  // Are there already requests pending?
  if ((params.id != null || get_more > 0) && (ajax_pending.length > 0 || want_more > .5)) {
    if ((new Date()).getTime() - ajax_last < 10000) {
      ajax_pending.push(params);
      want_more += get_more;
      return;
    }
  }

  if (params.id == null && ajax_pending.length > 0)
    params = ajax_pending.shift();

  want_more += get_more;
  if (want_more > 0)
    params.more = want_more;
  // always ask for 8 more scores
  var request = age_sorted.clone();
  request = request.splice(0, 8);
  age_sorted.splice(0, 8);
  age_sorted = age_sorted.concat(request);
  params.score = request.join(",");
  new Ajax.Request('serve.html', {parameters: params, onSuccess: function(trans) { if (!trans.responseJSON) { want_more = 0; } if (trans.responseJSON.search.length == 0) want_more /= 2; ReplaceItems(trans.responseJSON.search, trans.responseJSON.scores); if (want_more > .5 || ajax_pending.length > 0) DoRequest({}, 0); else $('waiting').hide(); }});
  $('waiting').show();
  ajax_last = (new Date()).getTime();
}

function UpdateModel(model) {
  var display = "";

  for (var ii = 0; ii < model.length; ii++)
    display += model_tag_template.evaluate({name: model[ii][0], title: model[ii][2]});

  $('model').innerHTML = display;

  for (var ii = 0; ii < model.length; ii++) {
    // get span within which the div can move
    var newdiv = $('model_' + model[ii][0]);
    ModelTag(newdiv, model[ii][0], model[ii][1]);
  }
}

function ModelTag(div, tag, weight) {
  new Control.Slider(div, 'model', {
    sliderValue: (weight + 1) / 2,
    onChange: function(v) {
      new Ajax.Request('adjust.html', {parameters: {tag: tag, weight: v}, onSuccess: function(trans) { }});
      DoRequest({}, 2);
    }
  });
}

function AddTag() {
  tag = $('addtag').value;
  new Ajax.Request('adjust.html', {parameters: {tag: tag}, onSuccess: function(trans) {}});
  DoRequest({}, 20);
  want_more = 20;
  $('addtag').value = '';
}

function ReplaceItems(search, rescores) {
  // sort search into array
  var divs = new Array();
  for (var ii = 0; ii < search.length; ii++)
    divs[search[ii][0]] = search[ii][1];

  for (var ii = 0; ii < rescores.length; ii++) {
    if (rescores[ii][0] == undefined) {
      return;
    }
    if (divs[rescores[ii][0]] == null) {
      if (scores[rescores[ii][0]] != -Infinity) {
        Rescore(rescores[ii][0], rescores[ii][1]);
      }
    } else {
      want_more -= TryAdd(rescores[ii][0], rescores[ii][1], divs[rescores[ii][0]]);
    }
  }
}

function TryAdd(id, score, div) {
  // find where to put this
  for (var ii = 0; ii < score_sorted.length; ii++)
    if (scores[score_sorted[ii]] < score) {
      // Add it!
      score_sorted.splice(ii, 0, id);

      var worstid = score_sorted.pop();
      var worstbox = boxes[worstid];

      // add it to our collection
      scores[id] = score;
      boxes[id] = worstbox;
      age_sorted.push(id);

      // remove the old from our collection
      if (scores[worstid] != -Infinity)
	age_sorted.splice(age_sorted.indexOf(worstid), 1);
      scores[worstid] = null;
      boxes[worstid] = null;

      var olddiv = worstbox.childElements().last();

      if (olddiv.visible()) {
        new Effect.SlideUp(olddiv);
        setTimeout(function() {
          $('replaced').insert({bottom: olddiv});
	  new Effect.SlideDown(olddiv);
        }, 1000);
        worstbox.insert({bottom: div});
        new Effect.SlideDown(worstbox.childElements().last());
      } else {
        worstbox.innerHTML = div;
        new Effect.SlideDown(worstbox.down());
      }

      return 1;
    }

  return 0;
}

function Rescore(id, score) {
  scores[id] = score;

  // remove from the score_sorted array
  var index = score_sorted.indexOf(id);
  if (index >= 0)
    score_sorted.splice(index, 1);

  if (score != -Infinity) {
    // find where to put this
    for (var ii = 0; ii < score_sorted.length; ii++)
      if (scores[score_sorted[ii]] < score) {
	score_sorted.splice(ii, 0, id);
	break;
      }
  } else
    score_sorted.push(id);

  // put at end of age_sorted
  // remove from the age_sorted array
  age_sorted.splice(age_sorted.indexOf(id), 1);

  if (score != -Infinity)
    age_sorted.push(id);
}  

