function next_load() {
   if (g_in_nl) { dBug("AH HAAAAAAAAAA"); return; }
   g_in_nl = 1;
   g_nln++;

   var debug = false;
//   if (debug) dBug("In next_load() #" + g_nln);
//   runaway++;
//   if (runaway > 2) return;
   var full_load = [];

   // go over each list.  Each list has a seed.  The first thing we need
   //  to do is fully load our seed
   for (var k in g_all_item_lists) {
      
      var this_list = g_all_item_lists[k];
      if (debug) dBug("Processing list id = " + this_list.list_id());

      for (var k2 in this_list.seeds) {
         var this_item_id = this_list.seeds[k2];
         var this_item = g_all_items[this_item_id];

   // check to see if this item is already loaded
         if (!this_item) { 
            if (debug) dBug("Item id = " + this_list.seeds[k2] +       
               " never loaded, added to queue");
            full_load.push(this_list.seeds[k2]);
         } else if (this_item.load_state() != K.LOAD_STATE_COMPLETE) {
            if (debug) dBug("Item id = " + this_list.seeds[k2] +       
               " not fully loaded, added to queue");
            full_load.push(this_item_id);
         } else {
            if (debug) dBug("Item id = " + this_list.seeds[k2] +       
               " fully loaded, not needed");
         }
      }
   }

   var xml = '';
   if (full_load.length > 0) {
      if (debug) dBug("Have 'never loaded' items, sending full load request");
      for (var k in full_load) {
         xml += _tag(K.TAG_WRAP_ITEM);
         xml += _tag_(K.TAG_ITEM_ID, full_load[k]);
   // desired version here...
         xml += tag_(K.TAG_WRAP_ITEM);
      }
      xml = _tag(K.TAG_WRAP_ITEMS) + xml + tag_(K.TAG_WRAP_ITEMS);
      do_ajax("/item_backend.php", process_inbound_item_data, 
         K.TAG_CMD_ITEM_LOAD, xml);
   }
   else {

      var list_load = [];
   // go over each item in each list.  If it is not collapsed,
   //  and if we don't have a child list, fetch one
//      for (var k in g_item_ids_uis) {
//         for (var j = 0 ; j < g_item_ids_uis[k].length; j++) {
//            var this_item =  g_item_ids_uis[k][j].item();
//
//            if (!this_item.children_loaded()) {
//               list_load[this_item.id()] = 1;
//            }
//   // kind of a hack, they're not really loaded yet but hard to catch this
//   //  later
//            this_item.set_children_loaded(true);
//         }
//      }
      for (var k in g_all_items) {
         var this_item = g_all_items[k];

         if (!this_item.children_loaded() && !this_item.is_hidden()) {
            list_load[k] = 1;
            g_all_items[k].set_children_loaded(true);
         }
      }

      if (list_load.length > 0) {
         for (var k in list_load) {
            xml += _tag(K.TAG_WRAP_ITEM);
            xml += _tag_(K.TAG_ITEM_ID, k);
            if (debug) dBug("Adding request for child list for item id " + k);
            xml += tag_(K.TAG_WRAP_ITEM);
         }
         xml = _tag(K.TAG_WRAP_ITEMS) + xml + tag_(K.TAG_WRAP_ITEMS);
         //send_ajax_request(ajax_item_r, K.TAG_CMD_CHILD_LIST, xml);
         do_ajax("/item_backend.php", process_inbound_item_data, K.TAG_CMD_CHILD_LIST, xml);
      } else {
         for (var k in g_all_items) {
            if (g_all_items[k].load_state() != K.LOAD_STATE_COMPLETE) {
               if (debug) dBug("Item id = " + k +       
                  " not fully loaded");
               full_load.push(k);
            }
         }       
         if (full_load.length > 0) {
            
            for (var k in full_load) {
               xml += _tag(K.TAG_WRAP_ITEM);
               xml += _tag_(K.TAG_ITEM_ID, full_load[k]);
         // desired version here...
               xml += tag_(K.TAG_WRAP_ITEM);
            }
            xml = _tag(K.TAG_WRAP_ITEMS) + xml + tag_(K.TAG_WRAP_ITEMS);
//            send_ajax_request(ajax_item_r, K.TAG_CMD_ITEM_LOAD, xml);
            do_ajax("/item_backend.php", process_inbound_item_data, K.TAG_CMD_ITEM_LOAD, xml);
         }

         if (debug) dBug("Nothing more to do!");
      }
   }
//   dBug("--------------"+g_nln+"-----------------------");
//   dBug("Next Load Done # " + g_nln);
   g_in_nl= 0;
}

// called, at least for now, but 'do_search'
function add_item_list_from_next_transaction(parent_el_in) {

   var il = item_list({list_id   : g_list_id_now, 
                       parent_el : parent_el_in });

   g_all_item_lists[g_list_id_now++] = il;

   // so we can find this list when the transaction comes in
   g_lists_transactions[g_trans_id] = il;

   return il;
}

function add_item_list_from_seed(parent_el_in, seed_in) {

   if (seed_in instanceof Array) {

   } else if (seed_in === null) {
      seed_in = [];
   } else {
      seed_in = [seed_in];
   }

   var il = item_list({list_id   : g_list_id_now, 
                       parent_el : parent_el_in ,
                       seeds : seed_in });

   g_all_item_lists[g_list_id_now++] = il;

   return il;
}

var g_pib = 0;

function process_delete_item(r)
{
   var root = r.doc.getElementsByTagName(K.TAG_ITEM_ID);
   
   for (var i = 0; i < root.length; i++)  
   {
      var item_id = root[i].childNodes[0].nodeValue;
  
   // unpick everything 
      for (var k in g_all_item_lists) {
         
         var this_list = g_all_item_lists[k];
         this_list.handle_pick_item(item_id, false);
      }

   // this is probably overkill...if an item is picked it will be deleted
   //  and unpicked, so why is this needed?
   // In any case, this goes to the trouble of unpicking children.  
      var the_item = g_all_items[item_id];
      var item_children = the_item.children_recur();

      for (var l = 0; l < item_children.length; l++) {
         for (var k in g_all_item_lists) {
            
            var this_list = g_all_item_lists[k];
            this_list.handle_pick_item(item_children[l], false);
         }  
      }
      
      // ...including any children that might have been picked

      var parent_id = g_all_items[item_id].parent_id();
      if (g_item_ids_uis[item_id] != undefined) {
         for (var j = 0 ; j < g_item_ids_uis[item_id].length; j++) {
// also remove from all_items
            g_item_ids_uis[item_id][j].remove();
         }
         g_all_items[item_id].remove();

      // fixup the orderint
         if (typeof g_item_ids_uis[parent_id] != 'undefined') {
            for (var j = 0 ; j < g_item_ids_uis[parent_id].length; j++) {
               g_item_ids_uis[parent_id][j].check_order();
            }
         }

// should be a function or MAP trick here
         if (parent_id && g_item_ids_uis[parent_id] != undefined) {
            for (var j = 0 ; j < g_item_ids_uis[parent_id].length; j++) {
               g_item_ids_uis[parent_id][j].draw();
            }
         }
      }
   }
}

function process_shift_item(r) {
   var root = r.doc.getElementsByTagName(K.TAG_ITEM_ID);
   
   var redraw_list = [];
   for (var i = 0; i < root.length; i++)  
   {
      var item_id = root[i].childNodes[0].nodeValue;
      var parent_id = g_all_items[item_id].parent_id();
      g_all_items[parent_id].set_children_loaded(false);
   }
   next_load();
}


function process_privacy(r)
{
   var is_recur = get_xml_value(r.doc, K.TAG_RECURSIVE);
   var is_read  = get_xml_value(r.doc, K.TAG_IS_READ);
   var new_mode = get_xml_value(r.doc, K.TAG_PRIVACY);

   var root = r.doc.getElementsByTagName(K.TAG_ITEM_ID);
   
   for (var i = 0; i < root.length; i++)  
   {
      var item_id = root[i].childNodes[0].nodeValue;

      var item_list;
      // if recursive, get all my children so I can fix them all.
      if (is_recur) {
         item_list = g_all_items[item_id].children_recur(); 
      } else {
         item_list = [];
         item_list.push(item_id);
      }

      // redraw_list needed because (perhaps unwisely) redraw_items_in_list
      //  wants stuff with array[534] = 1
      var redraw_list = [];
      for (var j = 0; j < item_list.length; j++) {
         var this_item_id = item_list[j];
         g_all_items[this_item_id].set_privacy(is_read, new_mode);
         redraw_list[this_item_id] = 1;
      }
      redraw_items_in_list(redraw_list);
   }
}

function process_attr_change(r)
{
   var mode     = get_xml_value(r.doc, K.TAG_MODE);
   var attrib   = get_xml_value(r.doc, K.TAG_WHICH_ATTRIB);
   var is_recur = get_xml_value(r.doc, K.TAG_RECURSIVE);
   var item_id  = get_xml_value(r.doc, K.TAG_ITEM_ID);

   var item = g_all_items[item_id]; 

   var item_list;
   // if recursive, get all my children so I can fix them all.
   if (is_recur) {
      item_list = item.children_recur();
   } else {
      item_list = [];
      item_list.push(item_id);
   }

   // redraw_list needed because (perhaps unwisely) redraw_items_in_list
   //  wants stuff with array[534] = 1
   var redraw_list = [];
   for (var i = 0; i < item_list.length; i++) {
      var this_item_id = item_list[i];
      redraw_list[this_item_id] = 1;
      var this_item = g_all_items[this_item_id];
      if (this_item) {
         this_item.set_attribute(attrib, mode == K.ITEM_ATTRIB_SET);
      }
   }

   // only need to possibly load anything if we are exposing something
   //  new
   if (mode != K.ITEM_ATTRIB_SET) {
      next_load();
   }

   redraw_items_in_list(redraw_list);
}

function process_add_item(r)
{
   var parent_id = get_xml_value(r.doc, K.TAG_PARENT_ID);
   if (parent_id !== null) {
      g_all_items[parent_id].set_children_loaded(false);
   }
   next_load();
}

function process_inbound_item_data(r)
{
   g_pib++;  
//   dBug("PIB IN  # " + g_pib + "(" + r.command + ")");
   var root = r.doc.getElementsByTagName(K.TAG_WRAP_ITEM);

   var new_item_data = [];

   // used so we can redraw / reorder when we have certain commands
   //  (like CHILD_LIST)
   for (var i = 0; i < root.length; i++)  
   {
      var d = root[i];

      var id_in = get_xml_value(d, K.TAG_ITEM_ID);

      // case for mass-update of hide/show
      if (!id_in)  {
         continue; // error display?
      }

      // 'spec' is our list of attributes.  We blindly suck down
      //   all the attributes and use it to make an item.  The item
      //   definition (below) will use up the valid ones
      var spec = {};
      spec[K.TAG_ITEM_ID] = id_in;

      var nodes = d.childNodes;

      for (var j = 0; j < nodes.length; j++)
      {  
         var tag_name = nodes[j].tagName;
         var tag_val  = node_val(nodes[j]);
         spec[tag_name] = tag_val;
      }

      // fix up children for the parent
      if (g_all_items[spec[K.TAG_PARENT_ID]]) {
         g_all_items[spec[K.TAG_PARENT_ID]].add_child(spec.id);
      }

      new_item_data.push(spec);
   }
   var check_order = (r.command == K.TAG_CMD_CHILD_LIST);
   process_ui_for_new_item_data(new_item_data, check_order);
//   dBug("PIB OUT  # " + g_pib);
}

function process_ui_for_new_item_data(new_item_data, check_order)
{
   var parents_detected = [];
   // a list of ids of items we have not received before
   var new_item_ids = [];
   var redraw_item_ids = [];

//dBug("{{{{-------- updating data");
   // first just upate the data
   for (var idx in new_item_data) {
      var spec = new_item_data[idx];

      var item_id = spec[K.TAG_ITEM_ID];

      var new_item = g_all_items[item_id];
      if (new_item) {
         new_item.update(spec);
      } else {
      //We store these sequentially else Chrome
      //  renders them out of order
         new_item = item( spec ); 
         g_all_items[item_id] = new_item;
      }
      new_item_ids.push(item_id);
      redraw_item_ids[item_id] = 1;

      // fix the parent.  
      parents_detected[new_item.parent_id()] = 1;
      if (g_all_items[new_item.parent_id()]) {
         g_all_items[new_item.parent_id()].add_child(item_id);
         redraw_item_ids[new_item.parent_id()] = 1;
      }

      new_item.flag_ui_wants_it();
   }

   // now update UIs
//dBug("[[[[[------- updating UI");
   for (var i = 0; i < new_item_ids.length; i++) {
      var x = new_item_ids[i];
      var this_item = g_all_items[x];

   // if this is a child, add it to the parent
      if (this_item.parent_id() && typeof g_item_ids_uis[this_item.parent_id()] != 'undefined') {
         for (var j = 0 ; j < g_item_ids_uis[this_item.parent_id()].length; j++) {
            g_item_ids_uis[this_item.parent_id()][j].add_child_ui(this_item.id());
         }
      }
   }
   if (check_order) {
      for (var k in parents_detected) {
   // find all item_uis for this parent.  check the order
         if (typeof g_item_ids_uis[k] != 'undefined') {
            for (var j = 0 ; j < g_item_ids_uis[k].length; j++) {
               g_item_ids_uis[k][j].check_order();
            }
         }
      }
   }

   redraw_items_in_list(redraw_item_ids);

   next_load();
/*       
   // if anyone is waiting to be dispatched on a transaction...    
   var trans_id = r.trans_id || null;
  
   if (typeof g_lists_transactions[trans_id] != 'undefined') {
      g_lists_transactions[trans_id].set_seeds(_new_item_ids);
   } 

//dBug("got: " + _new_items.length);
   

*/
   // finally, draw
}

