/**************************************************
 * 08.07.2005
 * Thumbnail selector from:
 * www.faith71.com, Lodewijk Bogaards
 **************************************************
 * Thumbnail Selector 
// SEMI-BUG: When aspect ratio is kept the dragging stops when cursor gets above img
 **************************************************/

function GetObjBounds(obj)
{ 
  if(!obj)
    throw new Error("GetObjBounds(): Null or undefined object passed");
  
  var xOffset, yOffset, width, height, elParent, elRoot; 
  
  if(typeof obj.offsetTop == 'number')
  { 
    yOffset = obj.offsetTop||0; 
    xOffset = obj.offsetLeft||0; 
    width = obj.offsetWidth;
    height = obj.offsetHeight;
    elParent = obj.offsetParent; 
    elRoot = document.documentElement;
    if (!elRoot)
      elRoot = document.body;
    while(elParent && elParent != elRoot)
    { 
      yOffset += elParent.offsetTop  || 0; 
      xOffset += elParent.offsetLeft || 0; 
      elParent = elParent.offsetParent; 
    } 
  }
  else if(typeof obj.top == 'number')
  { //some Net 4 DIVs 
    yOffset = obj.top; 
    xOffset = obj.left; 
    width = obj.width;
    height = obj.height;
  }
  else if(typeof obj.y == 'number')
  {  //Net 4 IMG & A 
    yOffset = obj.y; 
    xOffset = obj.x; 
    width = obj.width;
    height = obj.height;
  }
  else
  {   
    throw new Error("Could not get bounds for object: "+ obj.id);
  } 
  return {left:xOffset, top:yOffset, width:width, height:height}; 
} 
       
function TSRect_OnDrag()
{
  if (!this.ts_obj)
    return; 

  // get and set new bounds
  this.ts_obj.rect.bounds = GetObjBounds(this.ts_obj.rect);
  this.ts_obj.SetBoundsAbs(this.ts_obj.rect.bounds.left, this.ts_obj.rect.bounds.top, 
                           this.ts_obj.rect.bounds.width, this.ts_obj.rect.bounds.height);
}

function TSBBox_OnMouseover()
{
  if (!this.ts_obj)
    return; 

  if (this.ts_obj.bbox_alpha != 0)
  {
    if (this.ts_obj.bbox_hover_color && this.ts_obj.bbox_hover_color != "")
      this.style.backgroundColor = this.ts_obj.bbox_hover_color;
    if (this.ts_obj.bbox_hover_bgimage != '')
      this.style.backgroundImage = 'url('+this.ts_obj.bbox_hover_bgimage+')';
  }
  this.style.zIndex = 3;
}

function TSBBox_OnMouseout()
{
  if (!this.ts_obj)
    return; 

  if (this.ts_obj.bbox_alpha != 0)
  {
    if (this.ts_obj.bbox_color && this.ts_obj.bbox_color != "")
      this.style.backgroundColor = this.ts_obj.bbox_color;
    if (this.ts_obj.bbox_bgimage != '')
      this.style.backgroundImage = 'url('+this.ts_obj.bbox_bgimage+')';
  }
  this.style.zIndex = 2;
}

function TSBBox_OnDrag()
{
  if (!this.ts_obj)
    return; 

  var l, t, w, h, dx, dy, minw, minh;
  var postfix = this.id.substring(this.id.length-2, this.id.length);
  this.bounds = GetObjBounds(this);
 
  // get delta x and delta y 
  if (postfix.charAt(1) == "w")
    dx = this.ts_obj.rect.bounds.left - this.bounds.left; 
  else
    dx = (this.bounds.left+this.ts_obj.cur_bbox_size) - (this.ts_obj.rect.bounds.left+this.ts_obj.rect.bounds.width);
  if (postfix.charAt(0) == "n")
    dy = this.ts_obj.rect.bounds.top - this.bounds.top;
  else
    dy = (this.bounds.top+this.ts_obj.cur_bbox_size) - (this.ts_obj.rect.bounds.top+this.ts_obj.rect.bounds.height);
  
  if (dx == 0 && dy == 0) return;
  
  // get w and h
  minw = this.ts_obj.min_width;
  minh = this.ts_obj.min_height;
  w = this.ts_obj.width + dx;
  h = this.ts_obj.height + dy;

  if (this.ts_obj.keepaspect)
  {
   // keep aspect 
    var src_aspect = w / h;
    if (src_aspect < this.ts_obj.aspect)
      h  = Math.round(h / this.ts_obj.aspect * src_aspect);
    else
      w  = Math.round(w / src_aspect * this.ts_obj.aspect);
      
    // calculate aspected kept minimum width and height
    if (minw / minh != this.ts_obj.aspect)
    {
      minw = this.ts_obj.min_height * this.ts_obj.aspect;
      if (minw < this.ts_obj.min_width)
      {
        minh = this.ts_obj.min_width / this.ts_obj.aspect;
        minw = this.ts_obj.min_width;
      }
      else
        minh = this.ts_obj.min_height;
    }

    if (w <= minw || h <= minh)
    { 
      w = minw;
      h = minh;
    }
  }
  else
  {
    if (w < minw) w = minw;
    if (h < minh) h = minh;
  }

  // get l and t
  if (postfix.charAt(1) == "w")
    l = (this.ts_obj.rect.bounds.left+this.ts_obj.rect.bounds.width)-w;
  else
    l = this.ts_obj.rect.bounds.left;
  if (postfix.charAt(0) == "n")
    t = (this.ts_obj.rect.bounds.top+this.ts_obj.rect.bounds.height)-h;
  else
    t = this.ts_obj.rect.bounds.top;
 
  // set new this.rect bounds  
  this.ts_obj.SetBoundsAbs(l, t, w, h);
}

function TS_SetBounds(left, top, width, height)
{
  if (!this.initialized)
    throw new Error("ThumbnailSelector.SetBounds(): Thumbnail selector not initialized! Call ThumbnailSelector.Init() first.");

  this.SetBoundsAbs(left+this.img.bounds.left, top+this.img.bounds.top, width, height);
}


function TS_SetBoundsAbs(left, top, width, height)
{
  var tmp;
  
  if (!this.initialized)
    throw new Error("ThumbnailSelector.SetBoundsAbs(): Thumbnail selector not initialized! Call ThumbnailSelector.Init() first.");
 
  if (isNaN(left) || isNaN(top) || isNaN(width) || isNaN(height))
    return false;
    
  // round bounds
  left = Math.round(left);
  top = Math.round(top);
  width = Math.round(width);
  height = Math.round(height);
 
  // clip bounds
  if (left < this.img.bounds.left) left = this.img.bounds.left;
  if (top < this.img.bounds.top) top = this.img.bounds.top;
  if (width <= this.min_width) width = this.min_width;
  if (height <= this.min_height) height = this.min_height;
  if (left+this.min_width > this.img.bounds.left + this.img.bounds.width)
    left = this.img.bounds.left + this.img.bounds.width - this.min_width;
  if ((left + width) > (this.img.bounds.left + this.img.bounds.width)) 
    width  = (this.img.bounds.left + this.img.bounds.width)-left;
  if (top+this.min_height > (this.img.bounds.top + this.img.bounds.height))
    top = this.img.bounds.top + this.img.bounds.height - this.min_height;
  if ((top + height) > (this.img.bounds.top + this.img.bounds.height)) 
    height  = (this.img.bounds.top + this.img.bounds.height)-top;
    
  // set bounds properties for user
  this.left = left-this.img.bounds.left;
  this.top = top-this.img.bounds.top;
  this.width = width;
  this.height = height;
    
  // set box size 
  tmp = Math.max(1, Math.min(width, height));
  if (this.shrink_bbox && tmp < this.bbox_size*4)
    this.cur_bbox_size = Math.round(tmp/4);
  else 
    this.cur_bbox_size = this.bbox_size;
    
  // set this.rect
  this.rect.style.left = left;
  this.rect.style.top = top;
  this.rect.style.width = width;
  this.rect.style.height = height;
  this.rect.bounds = {left:left, top:top, width:width, height:height};
  this.rect.maxX = this.img.bounds.left+this.img.bounds.width-this.rect.bounds.width;
  this.rect.maxY = this.img.bounds.top+this.img.bounds.height-this.rect.bounds.height;

  // set this.rect_nw
  this.rect_nw.style.left = left;
  this.rect_nw.style.top = top;
  this.rect_nw.style.width = this.cur_bbox_size;
  this.rect_nw.style.height = this.cur_bbox_size;
  this.rect_nw.maxX = this.rect.bounds.left + this.rect.bounds.width;
  this.rect_nw.maxY = this.rect.bounds.top + this.rect.bounds.height;

  // set this.rect_ne
  this.rect_ne.style.left = left+width-this.cur_bbox_size;
  this.rect_ne.style.top = top;
  this.rect_ne.style.width = this.cur_bbox_size;
  this.rect_ne.style.height = this.cur_bbox_size;
  this.rect_ne.minX = this.rect.bounds.left;
  this.rect_ne.maxY = this.rect.bounds.top + this.rect.bounds.height;

  // set this.rect_sw
  this.rect_sw.style.left = left;
  this.rect_sw.style.top = top+height-this.cur_bbox_size;
  this.rect_sw.style.width = this.cur_bbox_size;
  this.rect_sw.style.height = this.cur_bbox_size;
  this.rect_sw.maxX = this.rect.bounds.left + this.rect.bounds.width;
  this.rect_sw.minY = this.rect.bounds.top;
  
  // set this.rect_se
  this.rect_se.style.left = left+width-this.cur_bbox_size;
  this.rect_se.style.top = top+height-this.cur_bbox_size;
  this.rect_se.style.width = this.cur_bbox_size;
  this.rect_se.style.height = this.cur_bbox_size;
  this.rect_se.minX = this.rect.bounds.left;
  this.rect_se.minY = this.rect.bounds.top;

  // set this.left_cover
  this.left_cover.style.left = this.img.bounds.left;
  this.left_cover.style.top = this.img.bounds.top;
  this.left_cover.style.width = this.rect.bounds.left-this.img.bounds.left;
  this.left_cover.style.height = this.img.bounds.height;

  // set thumb_right
  this.right_cover.style.left = this.rect.bounds.left+this.rect.bounds.width;
  this.right_cover.style.top = this.img.bounds.top;
  this.right_cover.style.width = (this.img.bounds.left+this.img.bounds.width)-(this.rect.bounds.left+this.rect.bounds.width);
  this.right_cover.style.height = this.img.bounds.height;

  // set this.top_cover
  this.top_cover.style.left = this.rect.bounds.left;
  this.top_cover.style.top  = this.img.bounds.top;
  tmp = Math.max(0, (this.rect.bounds.top-this.img.bounds.top));
  this.top_cover.style.height = tmp;
  if (tmp > 0)
    this.top_cover.style.width = this.rect.bounds.width;
  else
    this.top_cover.style.width = 0;

  // set this.bottom_cover
  this.bottom_cover.style.left = this.rect.bounds.left;
  this.bottom_cover.style.top  = this.rect.bounds.top+this.rect.bounds.height;
  tmp = Math.max(0, (this.img.bounds.top+this.img.bounds.height) -(this.rect.bounds.top+this.rect.bounds.height));
  this.bottom_cover.style.height = tmp;
  if (tmp > 0) 
    this.bottom_cover.style.width = this.rect.bounds.width;
  else
    this.bottom_cover.style.width = 0;

  return true;
}

function TS_OnWindowResize()
{
  if (!this.initialized)
    return false;
    
  // get image bounds again (image may have moved)
  // according to the selector <div> and not the <img>, because
  // that fails in IE for some reason.
  this.img.bounds = GetObjBounds(this.selector);
  // reset bounding minimum and maximums drag field for all dragable object
  this.rect.minX = this.img.bounds.left;
  this.rect.maxX = this.img.bounds.left+this.img.bounds.width-this.bbox_size;
  this.rect.minY = this.img.bounds.top;
  this.rect.maxY = this.img.bounds.top+this.img.bounds.height-this.bbox_size;
  for(var i = 0; i < this.bboxes.length; i++)
  {
    this.bboxes[i].minX = this.img.bounds.left;
    this.bboxes[i].maxX = this.img.bounds.left+this.img.bounds.width-this.bbox_size;
    this.bboxes[i].minY = this.img.bounds.top;
    this.bboxes[i].maxY = this.img.bounds.top+this.img.bounds.height-this.bbox_size;
  }
  // reset the bounds of the selection rectangle
  this.SetBounds(this.left, this.top, this.width, this.height);
  
  return true;
}

function TS_GetObjById(id)
{
  id = this.selector.id +'_'+ id;
  for (var i = 0; i < this.selector.childNodes.length; i++)
  { 
    if (this.selector.childNodes[i].id == id)
    {
      obj = this.selector.childNodes[i];
      break;
    }
  }
  if (!obj)
    throw new Error('Could not find "'+ id +'" object.');
  obj.ts_obj = this;
  return obj;
}

function TS_CreateDivHTML(id)
{
  return '<div id="'+ this.selector.id +'_'+ id +'" '+
         'style="position: absolute; z-index: 1; '+
         'background-image: url(x.gif); overflow: hidden;"></div>';
  
}

function TS_Init()
{
  if (!Drag)
    throw new Error("ThumbnailSelector.Init(): No drag object found! Load dom-drag.js first.");

  // adjust selector div's height to image
  this.img = this.selector.childNodes[0];
  if (!this.img)
    throw new Error("ThumbnailSelector.Init(): Thumbnail Selector div is empty!");
  if (!this.img.complete)
    throw new Error("ThumbnailSelector.Init(): Image is not loaded (yet)! Call ThumnailSelector.Init() when image is loaded.");
  
  // get image bounds
  this.img.bounds = GetObjBounds(this.img);
  
  // fit selector div around image
  this.selector.style.width = this.img.bounds.width;
  this.selector.style.height = this.img.bounds.height;
  
  var HTML = this.CreateDivHTML('left') + 
             this.CreateDivHTML('right') +
             this.CreateDivHTML('top') +
             this.CreateDivHTML('bottom') +
             this.CreateDivHTML('rect') +
             this.CreateDivHTML('rect_nw') +
             this.CreateDivHTML('rect_ne') +
             this.CreateDivHTML('rect_sw') +
             this.CreateDivHTML('rect_se') + 
             this.CreateDivHTML('rect_e');
                 
  
 // create thumb_selector divs
  this.selector.innerHTML += HTML;

  // get div objects
  this.rect    = this.GetObjById("rect");
  this.rect_nw = this.GetObjById("rect_nw");
  this.rect_ne = this.GetObjById("rect_ne");
  this.rect_sw = this.GetObjById("rect_sw");
  this.rect_se = this.GetObjById("rect_se");
  this.left_cover   = this.GetObjById("left");
  this.right_cover  = this.GetObjById("right");
  this.top_cover    = this.GetObjById("top");
  this.bottom_cover = this.GetObjById("bottom");

  this.covers = Array(this.left_cover, this.right_cover, this.top_cover, this.bottom_cover);
  this.bboxes = Array(this.rect_nw, this.rect_ne, this.rect_sw, this.rect_se);

  // setup initial rectangle coordinates (if not already specified by user)
  if (this.width == 0 && this.height == 0)
  {
    var src_aspect = this.img.bounds.width / this.img.bounds.height;
    
    if (src_aspect < this.aspect)
    {
      this.width   = this.img.bounds.width;
      this.height  = this.img.bounds.height / this.aspect * src_aspect;
    }
    else
    {
      this.width  = this.img.bounds.width / src_aspect * this.aspect;
      this.height = this.img.bounds.height;
    }    
    
    // set left and top in the middle
    this.left = (this.img.bounds.width / 2) - (this.width / 2);
    this.top  = (this.img.bounds.height / 2) - (this.height / 2);
  }

  // setup rectangle
  Drag.init(
    this.rect, 
    null, 
    this.img.bounds.left, 
    this.img.bounds.left+this.img.bounds.width-this.width, 
    this.img.bounds.top, 
    this.img.bounds.top+this.img.bounds.height-this.height
  );
  
  this.rect.onDrag = TSRect_OnDrag;
  this.rect.style.cursor = 'move';
  if (this.rect_bgimage != "")
  {
    this.rect.style.backgroundImage = 'url('+ this.rect_bgimage +')';
    this.rect.style.backgroundRepeat = 'repeat';
  }
  if (this.rect_border_width > 0 || this.rect_color != "")
  {
    var HTML = '<table style="border: '+ this.rect_border_width +'px solid '+ this.rect_border_color +'; ';
    if (this.rect_color && this.rect_color != "")
      HTML += 'background-color: '+ this.rect_color +'; ';
    HTML += '" width=100% height=100% cellspacing=0 cellpadding=0><tr><td></td></table>';
    this.rect.innerHTML = HTML; 
  }
  if (this.rect_alpha != 0)
    this.rect.style.filter = 'alpha(opacity='+ this.rect_alpha +')';
  

  // setup boundry boxes
  for (var i = 0; i < this.bboxes.length; i++)
  {
    if (this.bbox_alpha != 0)
    {
      this.bboxes[i].style.filter = 'alpha(opacity='+ this.bbox_alpha +')';
      this.bboxes[i].style.backgroundColor = this.bbox_color;
      if (this.bbox_bgimage != '')
        this.bboxes[i].style.backgroundImage = 'url('+ this.bbox_bgimage +')';
    }
    this.bboxes[i].style.cursor =  this.bboxes[i].id.substring(
                                    this.bboxes[i].id.length-2, 
                                    this.bboxes[i].id.length
                                   ) +'-resize';                            
  
    Drag.init(
      this.bboxes[i], 
      null, 
      this.img.bounds.left, 
      this.img.bounds.left+this.img.bounds.width-this.bbox_size, 
      this.img.bounds.top, 
      this.img.bounds.top+this.img.bounds.height-this.bbox_size
    );
    
    this.bboxes[i].onmouseover = TSBBox_OnMouseover;
    this.bboxes[i].onmouseout = TSBBox_OnMouseout;
    this.bboxes[i].onDrag = TSBBox_OnDrag;  
  } 
  
  // setup covers
  for(i = 0; i < this.covers.length; i++)
  {
    if (this.cover_alpha != 0)
    {
      if (this.cover_color && this.cover_color != "")
        this.covers[i].style.backgroundColor = this.cover_color;
      this.covers[i].style.filter = 'alpha(opacity='+ this.cover_alpha +')';
    }
    if (this.cover_image != "")
    {
      this.covers[i].style.backgroundImage = 'url('+ this.cover_bgimage +')';
      this.covers[i].style.backgroundRepeat = 'repeat';
    }
  }
  
  // done initializing. 
  this.initialized = true;
  this.SetBounds(this.left, this.top, this.width, this.height);
}

// ThumbnailSelector constructor
function ThumbnailSelector(selector_name, 
                           aspect, 
                           keepaspect,
                           l, t, w, h, 
                           minw, minh
                          )
{
  if (!selector_name)
    throw new Error("ThumbnailSelector.ThumbnailSelector(): No selector_name specified!");

  // initialize variables from parameters
  this.aspect     = aspect || 1.6;
  this.keepaspect = keepaspect || false;
  this.left = l || 0;
  this.top = t || 0;
  this.width = w || 0;
  this.height = h || 0;
  this.min_width = minw || 10;
  this.min_height = minh || 10;

  // appearance settings
  this.bbox_size = 10;
  this.bbox_color = "blue";
  this.bbox_hover_color = "red";
  this.bbox_bgimage = '';
  this.bbox_hover_bgimage = '';
  this.bbox_alpha = 80;
  this.shrink_bbox = true;

  this.cover_color = "#550000";
  this.cover_alpha = 85;
  this.cover_bgimage = "";

  this.rect_border_width = 5;
  this.rect_border_color = "red";
  this.rect_alpha = 30;
  this.rect_color = "";
  this.rect_bgimage = "";
  
  // initialize internal variables
  this.selector = document.getElementById(selector_name);
  this.cur_bbox_size = 0;
  this.bboxes = null;
  this.covers = null;
  this.rect = null;
  this.rect_nw = null;
  this.rect_ne = null;
  this.rect_sw = null;
  this.rect_se = null;
  this.left_cover = null;
  this.right_cover = null;
  this.top_cover = null;
  this.bottom_cover = null;
  this.img = null;
  this.initialized = false;

  // initialize methods
  this.SetBoundsAbs = TS_SetBoundsAbs;
  this.SetBounds = TS_SetBounds;
  this.OnWindowResize = TS_OnWindowResize;
  this.GetObjById = TS_GetObjById;
  this.CreateDivHTML = TS_CreateDivHTML;
  this.Init = TS_Init;
}


// global variable containing all ThumbnailSelector objects created with 
// CreateThumbnailSelector.
var ts_arr;

function OnWindowResizeThumbnailSelectors()
{
  if(!ts_arr)
    return;
  for(var i = 0; i < ts_arr.length; i++)
  {
    if (!ts_arr[i].selector) continue;
    ts_arr[i].OnWindowResize();
  }
}

function CreateTS(selector_name, 
                                aspect, 
                                keepaspect,
                                l, t, w, h, 
                                minw, minh)
{
  var ts;
  
  try
  {
    ts = new ThumbnailSelector(selector_name, aspect, keepaspect, l, t, w, h, minw, minh);
    ts.Init();
  }
  catch(e)
  {
    alert('CreateThumbnailSelector() catched error: "'+ e +'".');
  }
  
  if (!ts)
    return null;
    
  if (!ts_arr)
    ts_arr = Array(ts);
  else
    ts_arr[ts_arr.length] = ts;
    
  window.onresize = OnWindowResizeThumbnailSelectors;
  
  return ts;
}

function GetTS(selector_name)
{
  for (var i = 0; i < ts_arr.length; i++)
  {
    if (!ts_arr[i].selector) continue;
    if (ts_arr[i].selector.id == selector_name)
    { 
      return ts_arr[i];   
      }
  }
  return null;
}


