function init()
{
  icon = new Array(); // array will contain all visible icons
  zIndex = new Array(); // array of icons sorted by zIndex (lowest first)
  dragged_item = new Number(); // number of icon that is dragged
  margin = 64; // margin (px); icons cannot be moved beyond margin @ left & bottom
  loaded = false; // disable mouseOver icon-shift effect when icons not loaded completely
  update = "notupdated"; // flag to indicate if icons positions are already updated at server
  var now = new Date();
  t_pick = now.getTime(); // initialize pick-up time
  pile_name = ""; // initialize pile_name
  shifted = false; // icons not shifted by default
  need_update = false;
  move_done = false;
// left_window = false;
}

// Enable document wide events and enable mouseOver icon-shift effect
function finish(pilename)
{
//  document.captureEvents(onmouseout);
  document.onmousemove = mouseMove; // enable/capture mouseMove event
  document.onmouseup = function () {icon[parseInt(dragged_item)].dragging = false; return true;} // document wide stop dragging when mouseUp

  document.onmouseout = function (e) {
//    if (loaded && icon[parseInt(dragged_item)].dragging && move_done) left_window = true;
    if (!e) var e = event; // explicitly get event if not already given (some browsers need this)
    if (e.clientX < 0 || e.clientX >= win_x || e.clientY < 0 || e.clientY >= win_y) icon[parseInt(dragged_item)].dragging = false;
    return true;
  } // document wide stop dragging when mouse leaves browser window

//  document.onmouseover = function (e) {
//    if (!e) var e = event; // explicitly get event if not already given (some browsers need this)    
//    if ((!ie && e.which == 1) || (ie && e.button == 1)) alert ("Hi"); 
//    alert(e.which);
//    return false;
//  }

  if (document.getElementById('popupmenu')) enable_menu(); // enable popup menu if menu object is present (= in admin mode)

  window.onresize = function () {getWindowSize(); resizeItemFrame(win_x, win_y);} // update window size variables and resize item frame after resize
//  getWindowSize;
//  resizeItemFrame(win_x,win_y);
  pile_name = pilename; // store pile name
  loaded = true; // enable mouseOver icon-shift effect
}

// Quick sort core algorithm
function quick_sort(arry, col, cols, lo_par, hi_par)
{
  var lo = lo_par;
  var hi = hi_par;
  var mid = 0;
  var temp = 0;
  if (col>=cols) col=0;
  if (hi_par > lo_par)
  {
    mid = arry[Math.floor((lo_par+hi_par)/2)*cols+col];
    while (lo<=hi)
    {
      while (lo<hi_par && arry[lo*cols+col]<mid)
        lo++;
      while (hi>lo_par && arry[hi*cols+col]>mid)
        hi--;
      if (lo<=hi)
      {
        for (var i=0; i<cols; i++)
	{
	  temp = arry[lo*cols+i];
	  arry[lo*cols+i] = arry[hi*cols+i];
	  arry[hi*cols+i] = temp;
	}
	lo++;
	hi--;
      }
    }
    if (lo_par<hi) quick_sort(arry, col, cols, lo_par, hi);
    if (lo<hi_par) quick_sort(arry, col, cols, lo, hi_par);
  }
  return arry;
}

// Array sort routine (col=column to sort on; cols=total number of columns)
function sort_array(arry, col, cols)
{
  sorted_arry = new Array(arry.length);
  sorted_arry = quick_sort(arry, col, cols, 0, arry.length/cols - 1);
  return sorted_arry;
}

// Serialize array into a single string
function serialize(arry)
{
  var str = "";
  for (var i=0; i<arry.length; i++)
  {
    str+=arry[i]; // add element
    if (i<arry.length-1) str+=","; // comma separated list of elements
  }
  return str;
}

// Place caption in center of image
function place_caption(icon_name)
{
  var image_obj = document.getElementById(icon_name);
  var caption_obj = document.getElementById(icon_name+'_caption');
  var caption_width = caption_obj.offsetWidth;
  var caption_height = caption_obj.offsetHeight;
  var image_width = parseInt(image_obj.style.width);
  var image_height = parseInt(image_obj.style.height);
  caption_obj.style.left = Math.round((image_width - caption_width)/2) + 'px';
  caption_obj.style.top = Math.round((image_height - caption_height)/2) + 'px';
  caption_obj.onmousedown = function () {return true;};
  caption_obj.onmouseup = function () {return true;};
  caption_obj.onmouseover = function () {return false;};
  caption_obj.onmouseout = function () {return false;};
  return true;
}

// Read in image into icon-array
function read_image(icon_name, icon_url, icon_type, icon_status)
{	
  var i = icon.length; // first free entry in icon array
  icon[i] = document.getElementById(icon_name);
  icon[i].name = icon_name;
  icon[i].link = icon_url;
  icon[i].type = icon_type;
  icon[i].status = icon_status;
  icon[i].idx = i; // icon index/number
  var x = parseInt(icon[i].style.left);
  var y = parseInt(icon[i].style.top);
  x = (x < win_x - margin) ? x : win_x - margin;
  y = (y < win_y - margin) ? y : win_y - margin;
  x = (x < margin - parseInt(icon[i].style.width)) ? margin - parseInt(icon[i].style.width) : x;
  y = (y < margin - parseInt(icon[i].style.height)) ? margin - parseInt(icon[i].style.height) : y;
  icon[i].style.left = x + "px";
  icon[i].style.top = y + "px";
  icon[i].def_x = x; // store start position (to detect 'has been moved')
  icon[i].def_y = y;
  icon[i].x_old = 65535; // initialize old icon position
  icon[i].y_old = 65535;
  icon[i].x_shift = 0; // initialize icon shift values
  icon[i].y_shift = 0;
  icon[i].dragging = false;
  icon[i].onmousedown = mouseDown;
  icon[i].onmouseup = mouseUp;
  icon[i].onmouseover = mouseOver;
  icon[i].onmouseout = mouseOut;
  zIndex[icon[i].style.zIndex] = i; // put icon number in zIndex LUT
  place_caption(icon_name);
  return true;
}

// Fill-in the update form and submit this form to update icon positions, etc.
function submit_update()
{
  link_form = window.frames["update_frame"].document.getElementById('link_form'); // object link-form in hidden update iframe
  if (link_form) {
    link_form.pile_name.value = pile_name; // pass pile_name to update page
    link_form.dragged_icons.value = dragged_icons; // put dragged icons array in link-form to post it to server 
    if (icon_obj != "notupdated")
    {
      link_form.url.value = icon_obj.link;
      link_form.icon_type.value = icon_obj.type;
    } else {
      link_form.url.value = "";
      link_form.icon_type.value = "";
    }
    update = "updated"; // update only once
    link_form.submit(); // submit data to update.php in hidden iframe
  } else {
    need_update = true; // need to update the iframe (apparently the update.php page is still in the iframe)
    window.frames["update_frame"].location.href = 'update_form.html'; // load update_form.html in the iframe
  }
  return false;
}

// Update icon position and zIndex at server
function update_icons(icon_obj_param)
{
  icon_obj = icon_obj_param; // make it global
  if(icon_obj && icon_obj != "updated")
  {
    var j = 0;
    dragged_icons = new Array(); // array of icons that have been moved
    for (var i=0; i<icon.length; i++)
    {
      var x = parseInt(icon[i].style.left) - icon[i].x_shift; // do not consider icon shift as move
      var y = parseInt(icon[i].style.top) - icon[i].y_shift;
      if (x != icon[i].def_x || y != icon[i].def_y) // icons moved?
      {
	icon[i].def_x = x; // take over new position as default
	icon[i].def_y = y;
	dragged_icons[j] = icon[i].name;
        dragged_icons[j+1] = x;
        dragged_icons[j+2] = y;
        dragged_icons[j+3] = parseInt(icon[i].style.zIndex);
	j+=4;
      }
    }
    dragged_icons = sort_array(dragged_icons, 3, 4); // sort array on zIndex (lowest first)
    submit_update(); // fill-in the update_form with params & submit form to update icon positions, etc.
  }
  return false;
}

// Mouse down event handler
function mouseDown(e)
{
  if (!e) var e = event; // explicitly get event if not already given (some browsers need this)
  if (window.proc_menu_on_item) if (proc_menu_on_item(this.name) && (e.shiftKey || e.ctrlKey || e.altKey || e.metaKey)) return false; // in admin mode: don't start moving if modifier keys pressed
  var now = new Date();
  t_pick = now.getTime(); // store pick-up time
  if (loaded) document.getElementById(this.name + "_caption").style.visibility = "visible"; // icon caption visible
  if (!this.dragging)
  {
    this.dragging = true;
    this.dx = e.clientX - parseInt(this.style.left); // prevent cursor snapping
    this.dy = e.clientY - parseInt(this.style.top);
    this.old_x = parseInt(this.style.left); // store previous position used for dead zone effect
    this.old_y = parseInt(this.style.top);
    dragged_item = this.idx;
  }
  else
    this.dragging = false; // just to be sure: prevent sticky icons
  return false;
}

// Mouse move event handler
function mouseMove(e)
{
  if (!e) var e = event;
  var i = new Number(dragged_item); // convert from string to integer
  if (ie && !e.button) 
  {
    icon[i].dragging = false;
    return false; // don't move if mouse button not pressed (only works in MSIE)
  }
  if (icon[i].dragging && (icon[i].status & 1))
  {
    if (icon[i].style.zIndex != icon.length - 1) // icon not already on top
    {
      var z = new Number(icon[i].style.zIndex);
      for (var j=z+1; j<icon.length; j++) // move icons above current down wrt. zIndex
      {
        icon[zIndex[j]].style.zIndex = icon[zIndex[j]].style.zIndex - 1;
        zIndex[j-1] = zIndex[j];
      }
      icon[i].style.zIndex = icon.length - 1; // current icon on top
      zIndex[icon.length - 1] = i; // also in zIndex LUT
    }
    var x = e.clientX - icon[i].dx;
    var y = e.clientY - icon[i].dy;
    x = (x < win_x - margin) ? x : win_x - margin; // don't exceed margin
    y = (y < win_y - margin) ? y : win_y - margin;
    x = (x < margin - parseInt(icon[i].style.width)) ? margin - parseInt(icon[i].style.width) : x;
    y = (y < margin - parseInt(icon[i].style.height)) ? margin - parseInt(icon[i].style.height) : y;
    icon[i].style.left = x + "px";
    icon[i].style.top = y + "px";
    document.getElementById(icon[i].name + "_caption").style.visibility = "visible"; // icon caption visible, even if mouse moved too fast
  }
  move_done = true;
  return true;
}

// Mouse up event handler
function mouseUp(e)
{
  this.dragging = false; // stop dragging
  if (!shifted) document.getElementById(this.name + "_caption").style.visibility = "visible"; // icon caption invisible, even if mouseOut already happened
  var dead_zone = 2; // dead zone in px
  if (Math.abs(parseInt(this.style.left) - this.old_x) <= dead_zone || Math.abs(parseInt(this.style.top) - this.old_y) <= dead_zone) // icon moved more than dead zone?
  {
    var click_speed = 200; // click speed in ms
    var now = new Date(); 
    t_drop = now.getTime();
    if (t_drop - t_pick < click_speed) // clicked instead of slow mouse down - mouse up?
      update_icons(this); // update icon positions and follow link
  }
  return true;
}

// Mouse over event handler
function mouseOver(e)
{
//  alert("MouseOver");
  var shift = 3; // icon shift in px
  if (!e) var e = event;
  if (this.dragging || !loaded) return false; // no shift if icon is dragged or icons not loaded completely
  if (shifted) return false; // skip shift if already shifted
  var xc = parseInt(this.style.left) + parseInt(this.style.width)/2; // calculate center of icon
  var yc = parseInt(this.style.top) + parseInt(this.style.height)/2;
  var dx = (e.clientX - xc);
  var dy = (e.clientY - yc);
  var len = Math.sqrt(dx*dx+dy*dy);
  this.x_shift = Math.round(dx*shift/len); // shift in direction of mouse pointer
  this.y_shift = Math.round(dy*shift/len); // store shift to be able to unshift
  var x = this.x_shift + parseInt(this.style.left);
  var y = this.y_shift + parseInt(this.style.top);
  this.style.left = x + "px";
  this.style.top = y + "px";
  document.getElementById(this.name + "_caption").style.visibility = "visible"; // icon caption visible
  shifted = true; // prevent invalid shifts
  return false;
}

// Mouse out event handler
function mouseOut(e)
{
  if (!e) var e = event;
  if (!loaded) return false; // no shift if icons not loaded completely
//  if (!shifted) return false; // don't unshift if not shifted
  var x = parseInt(this.style.left) - this.x_shift; // unshift
  var y = parseInt(this.style.top) - this.y_shift;
  this.x_shift = 0; // reset shift values
  this.y_shift = 0;
  this.style.left = x + "px";
  this.style.top = y + "px";
  document.getElementById(this.name + "_caption").style.visibility = "hidden"; // icon caption invisible
  shifted = false; // allow new icon shifts
  return false;
}

init(); // Initialize arrays and variables immediately
