function ImageDescLoader() {
  this.CurKey = null;
  this.KeyDescSets = {};
  this.MaxImageDescsHigh = 1000;
  this.MaxImageDescsLow = 500;
  this.MaxImageDescsHigh = 300;
  this.MaxImageDescsLow = 200;
}

ImageDescLoader.prototype.set_cur_key = function(cur_key) {
  this.CurKey = cur_key;
};


ImageDescLoader.prototype.get_desc_set = function(
  cgi_desc_sets,
  key,
  mod_date,
  loc_hint,
  success_callback,
  failure_callback
) {
  var obj = this;

  if (key != null && obj.KeyDescSets[key] != null) {
    success_callback(key, obj.KeyDescSets[key].ImageDescs);
    return;
  }

  var desc_set;
  if (desc_set != null) {
    if (mod_date == null || mod_date <= desc_set.mod_date) {
      obj.KeyDescSets[key] = desc_set;
      obj.KeyDescSets[key].LocHint = loc_hint;
      success_callback(key, obj.KeyDescSets[key].ImageDescs);
      obj.collect_garbage();
      return;
    }
    else {
    }
  }

  if (cgi_desc_sets == null) {
    failure_callback('no cgi_desc_sets provided');
    return;
  }

  $.ajax({
    type: "GET",
    url: "/ecom/event_images_json.pl",
    data: {
      desc_set: cgi_desc_sets
    },
    dataType: "json",
    success: function(data) {
      if (data.Images != null) {
	obj.KeyDescSets[key] = {
	  ImageDescs: data.Images
	};
	var desc_set = obj.KeyDescSets[key];
        desc_set.LocHint = loc_hint;
        success_callback(key, desc_set.ImageDescs);
	obj.collect_garbage();
      }
      else if (data.Error != null) {
	failure_callback('error loading image set: '+data.Error);
      }
      else {
	failure_callback('unknown error loading image set');
      }
    },
    error: function() {
      failure_callback('unknown error loading image set');
    }
  });
};

ImageDescLoader.prototype.collect_garbage = function() {
  var obj = this;

  var num_image_descs = 0;
  for (var key in obj.KeyDescSets)
    num_image_descs += obj.KeyDescSets[key].ImageDescs.length;
  if (num_image_descs <= this.MaxImageDescsHigh) return;

  var loc_hint_comps = obj.KeyDescSets[obj.CurKey].LocHint.split('-');
  var cur_folder = loc_hint_comps[0];
  var cur_event_idx = loc_hint_comps[1];
  var cur_page_idx = loc_hint_comps[2];
  var score_keys = {};
  var scores = [];
  for (var key in obj.KeyDescSets) {
    loc_hint_comps = obj.KeyDescSets[key].LocHint.split('-');
    var cmp_folder = loc_hint_comps[0];
    var cmp_event_idx = loc_hint_comps[1];
    var cmp_page_idx = loc_hint_comps[2];
    var score;
    if (cur_event_idx == cmp_event_idx)
      score = Math.abs(cur_page_idx - cmp_page_idx);
    else
      score = 5 * Math.abs(cur_event_idx - cmp_event_idx);
    if (score_keys[score] == null) {
      score_keys[score] = [];
      scores.push(score);
    }
    score_keys[score].push(key);
  }

  scores.sort(function(a, b) { return b - a; });
  var evict_keys = [];
  var new_num_image_descs = num_image_descs;
  for (var i = 0; i < scores.length; i++) {
    var score = scores[i];
    for (var j = 0; j < score_keys[score].length; j++) {
      var key = score_keys[score][j];
      evict_keys.push(key);
      new_num_image_descs -= obj.KeyDescSets[key].ImageDescs.length;
      if (new_num_image_descs < obj.MaxImageDescsLow) break;
    }
    if (new_num_image_descs < obj.MaxImageDescsLow) break;
  }

  for (var i = 0; i < evict_keys.length; i++) {
    var evict_desc_set = obj.KeyDescSets[evict_keys[i]];
    delete obj.KeyDescSets[evict_keys[i]];
  }
};

