/*

 rubber.js -- a base class for drag/rubber-band selection in gbrowse

 Sheldon McKay <mckays@cshl.edu>
 $Id: rubber.js,v 1.1.2.11 2008/01/26 20:07:48 sheldon_mckay Exp $

*/

var currentSelectArea;
var selectAreaIsActive;
var regionType;

// Constructor
var SelectArea = function () {
  return this;
}

// Cross-browser element coordinates
SelectArea.prototype.elementLocation = function(el,request) {
  var region = YAHOO.util.Dom.getRegion(el);
  switch(request) {
    case ('y1') : return region.top;
    case ('y2') : return region.bottom;
    case ('x1') : return region.left;
    case ('x2') : return region.right;
    case ('width')  : return (region.right - region.left);
    case ('height') : return (region.bottom - region.top);
 }
}


// Cross-browser event coordinates
SelectArea.prototype.eventLocation = function(event,request) {
  var e = event || window.event;
  if (request == 'x') {
    return e.pageX || e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
  }
  else if (request == 'y') {
    return e.pageY || e.clientY + document.body.scrollTop  + document.documentElement.scrollTop;
  }
  else {  
    return false;
  }
}

// Fired when there is a mousedown between the top and bottom
// of the selectable image -- horizontal position does not matter
SelectArea.prototype.startRubber = function(self,event) {
	
	var click_x = self.eventLocation(event,'x');
	var click_y = self.eventLocation(event,'y');
	var x1 = self.left;
	var y1 = self.top;
//	document.getElementById('status_line').innerHTML = click_x +"-"+ x1 + ", " + self.padLeft + ", " + self.padRight;
	regionType = (click_y - y1 < self.padTop)? 1: 2;
	if(regionType == 1 && (click_x - x1 < self.padChromLeft || click_x - x1 > self.padRight)) {return false;}
	if(regionType == 2 && (click_x - x1 < self.padLeft || click_x - x1 > self.padRight)) {return false;}
	
  // only one select area is active at a time, so let the subclass take possession
  currentSelectArea = self;

  // set the selectbox bgcolor
  self.setOpacity(self.selectBox,self.opacity);  

  // deal with drag/select artifacts
  self.disableSelection(self.selectLayer);

  self.selectPixelStart = click_x;
  
  // height of select box to match height of detail panel
  var h = self.elementLocation(self.selectLayer,'height');
  YAHOO.util.Dom.setStyle(self.selectBox,'height',h+'px');
  
  // vertical offset may also need adjusting
  var t = self.elementLocation(self.selectLayer,'y1');
  YAHOO.util.Dom.setStyle(self.selectBox,'top',t+'px');

  selectAreaIsActive = true;
}

SelectArea.prototype.cancelRubber = function() {
  var self = currentSelectArea || new SelectArea;

  if (!self.selectBox) return false;
  
  YAHOO.util.Dom.setStyle(self.selectBox,'visibility','hidden');
  YAHOO.util.Dom.setStyle(self.selectMenu,'visibility','hidden');
  selectAreaIsActive = false;

  if (self.originalLandmark) {
    document.mainform.name.value = self.originalLandmark;
  }
  self.moved = false;
}

SelectArea.prototype.round = function(nearest,num) {
  if (num > nearest) {
    num = Math.round(num/nearest)*nearest;
  }
  return num;
} 

SelectArea.prototype.outRubber = function(event) {
	SelectArea.prototype.cancelRubber();
}

SelectArea.prototype.moveRubber = function(event) {
  if (!selectAreaIsActive) return false;

  var self = currentSelectArea;

	var click_x = self.eventLocation(event,'x');
	var click_y = self.eventLocation(event,'y');
	var x1 = self.left;
	var y1 = self.top;
//	document.getElementById('status_line').innerHTML = click_x - x1 + ", " + self.padLeft + ", " + self.padRight;
	if(regionType != 1 && click_y - y1 < self.padTop) {self.cancelRubber(); return false;}
	if(regionType != 2 && click_y - y1 > self.padTop) {self.cancelRubber(); return false;}
	if(regionType == 1) {
		if(click_x - x1 < self.padChromLeft) {click_x = self.padChromLeft * 1 + x1 * 1;}
		if(click_x - x1 > self.padRight)     {click_x = self.padRight * 1 + x1 * 1;}
	} else {
		if(click_x - x1 < self.padLeft)  {click_x = self.padLeft * 1 + x1 * 1;}
		if(click_x - x1 > self.padRight) {click_x = self.padRight * 1 + x1 * 1;}
	}

  var selectPixelStart = self.selectPixelStart;
  var selectPixelEnd   = click_x;
  var selectPixelWidth = Math.abs(selectPixelStart - selectPixelEnd);

  var rev, left;
  if (selectPixelStart > selectPixelEnd) {
    rev  = true;
    left = selectPixelEnd;
    self.selectPixelStart = left;
  } else {
    left = selectPixelStart;
  }

  // Coordinates of selected sequence
  var deltaPixelStart      = left - ((regionType == 1)? self.pixelChromStart: self.pixelStart);
  var deltaSequenceStart   = deltaPixelStart * ((regionType == 1)? self.pixelToChromDNA: self.pixelToDNA);
  self.selectSequenceStart = Math.round(((regionType == 1)? 1: self.segmentStart) + deltaSequenceStart);
  var selectSequenceWidth  = Math.round(selectPixelWidth * ((regionType == 1)? self.pixelToChromDNA: self.pixelToDNA));
  self.selectSequenceEnd   = self.selectSequenceStart + selectSequenceWidth - 1;
  if(self.selectSequenceEnd < self.selectSequenceStart) self.selectSequenceEnd = self.selectSequenceStart;

  var segmentLength = Math.abs(self.segmentEnd - self.segmentStart);

  // reset the value of the 'name' input box
  self.currentSegment = self.ref +':'+self.selectSequenceStart+'..'+self.selectSequenceEnd;
  //alert("mente:"+self.currentSegment);
  document.mainform.name.value = self.currentSegment;

  // size and appearance of the "rubber band" select box
	var up_pix = 122;
	var height_size = self.bottom - y1 + 1 - self.padTop;
	if(regionType == 1) {
		YAHOO.util.Dom.setStyle(self.selectBox,'top',y1 * 1 + 5 * 1 + 'px');
		YAHOO.util.Dom.setStyle(self.selectBox,'height', '25px');
	} else {
		YAHOO.util.Dom.setStyle(self.selectBox,'top',y1 * 1 + self.padTop * 1 - 5 + 'px');
		YAHOO.util.Dom.setStyle(self.selectBox,'height',height_size + 'px');
	}
  YAHOO.util.Dom.setStyle(self.selectBox,'left',(left - 3)+'px');
  YAHOO.util.Dom.setStyle(self.selectBox,'width',selectPixelWidth+'px');
  YAHOO.util.Dom.setStyle(self.selectBox,'visibility','visible');

  self.selectPixelStart = selectPixelStart;
  self.moved = true;
}

// taken from http://ajaxcookbook.org/disable-text-selection/
// prevents ugly drag select side-effects
SelectArea.prototype.disableSelection = function(el) {
    el.onselectstart = function() {
        return false;
    };
    el.unselectable = "on";
    el.style.MozUserSelect = "none";
    el.style.cursor = "default";
}


// Builds the popup menu that appears when selection is complete
SelectArea.prototype.addSelectMenu = function(view) {

  var menu =  document.getElementById(view+'SelectMenu') 
           || this.createAndAppend('div',document.body,view+'SelectMenu');

  // required style 
  YAHOO.util.Dom.setStyle(menu,'position','absolute');
  YAHOO.util.Dom.setStyle(menu,'display','block');
  YAHOO.util.Dom.setStyle(menu,'z-index','101');
  YAHOO.util.Dom.setStyle(menu,'visibility','hidden');

  // optional style -- check if a custom menu has styles set already
  var existingStyle = new String(menu.getAttribute('style'));
  if (existingStyle) {
    if (!existingStyle.match(/width/i))      YAHOO.util.Dom.setStyle(menu,'width',this.menuWidth||'200px');
    if (!existingStyle.match(/font/i))       YAHOO.util.Dom.setStyle(menu,'font','12px sans-serif');
    if (!existingStyle.match(/background/i)) YAHOO.util.Dom.setStyle(menu,'background','lightyellow');
    if (!existingStyle.match(/border/i))     YAHOO.util.Dom.setStyle(menu,'border','1px solid #003366');
  }

  this.selectMenu = menu;
  this.formatMenu();
}

// Initial creation of the select box
SelectArea.prototype.addSelectBox = function() {
  if (this.selectBox) return false;
 
  var box = this.createAndAppend('div',this.selectLayer);

  YAHOO.util.Dom.setStyle(box,'position','absolute');
  YAHOO.util.Dom.setStyle(box,'display', 'inline');
  YAHOO.util.Dom.setStyle(box,'visibility', 'hidden');
  YAHOO.util.Dom.setStyle(box,'top',this.top+'px');
  YAHOO.util.Dom.setStyle(box,'left','0px');
  YAHOO.util.Dom.setStyle(box,'z-index',100);
  YAHOO.util.Dom.setStyle(box,'border',this.border||'none');

  // click on scalebar initializes selection
  this.scalebar.onmousedown = this.startSelection;

  // drag and mouseup on details panel fires menu
  this.selectLayer.onmousemove   = this.moveRubber;
  this.selectLayer.onmouseup     = this.stopRubber;  
	
  // allows drag-back
  box.onmousemove           = this.moveRubber;
  
  this.selectBox = box;
}


/////////////////////////////////////////////////////////////////////
// Create/append  elements
/////////////////////////////////////////////////////////////////////

SelectArea.prototype.createAndAppend = function(elTag,parent,id) {
  var node = this.justCreate(elTag);
  this.justAppend(node,parent);
  if (id) node.setAttribute('id',id);
  return node;
}

SelectArea.prototype.justCreate = function(elTag) {
  var tag = elTag || 'div';
  var node = document.createElement(tag);
  return node;
}

SelectArea.prototype.justAppend = function(child,parent) {
  var parentNode = parent || document.body;
  parentNode.appendChild(child);
}
  

SelectArea.prototype.stopRubber = function(event) {
  if (!selectAreaIsActive) return false;
  var self = currentSelectArea;
  if (!self.moved) {
    self.cancelRubber();
    return false;
  }

  selectAreaIsActive = false;
  self.moved = false;
	
//	document.getElementById('status_line').innerHTML = self.spid + "!" + self.chrom_id + "!" + self.selectSequenceStart + "!" + self.selectSequenceEnd + "!1";
	change_viewer(self.spid, self.chrom_id, self.selectSequenceStart, self.selectSequenceEnd, 1, self.srh);

//  self.showMenu(event);
}

SelectArea.prototype.showMenu = function(event) {
  var self = currentSelectArea;
  var menu = self.selectMenu;
  menu.innerHTML = self.menuHTML.replace(/SELECTION/g,self.currentSegment);

  var pageWidth  = YAHOO.util.Dom.getViewportWidth();
  var menuWidth  = self.elementLocation(menu,'width');
  var menuHeight = self.elementLocation(menu,'height');
  var menuYHalf  = Math.round(menuHeight/2); 
  
  var left = self.eventLocation(event,'x') + 5;
  if ((left+menuWidth) > pageWidth) left -= menuWidth + 10;
  var top  = self.eventLocation(event,'y') - menuYHalf;

  YAHOO.util.Dom.setStyle(menu,'top',  top+'px'); 
  YAHOO.util.Dom.setStyle(menu,'left', left+'px');

  // Abort if there is no selection
  if (YAHOO.util.Dom.getStyle(self.selectBox,'visibility') == 'hidden') {
    self.cancelRubber;
    return false;
  }

  YAHOO.util.Dom.setStyle(menu,'visibility','visible');

}

SelectArea.prototype.hideMenu = function() {
  var self = currentSelectArea;

  YAHOO.util.Dom.setStyle(self.selectBox,'width',1);  
  YAHOO.util.Dom.setStyle(self.selectBox,'visibility','hidden');
  YAHOO.util.Dom.setStyle(self.selectMenu,'visibility','hidden');
}

SelectArea.prototype.clearAndSubmit = function(plugin,action) {
  this.hideMenu();
  if (plugin) {
    action = action || 'Go';
    var url = window.location;
    url += '?plugin='+plugin+';plugin_do='+action; 
    document.location = url;
  }
  else {
    document.mainform.submit();
  }
}

SelectArea.prototype.clearAndRecenter = function() {
  var self = currentSelectArea;
  var start   = document.mainform.start.value.replace(/\D+/,'') * 1;
  var end     = document.mainform.stop.value.replace(/\D+/,'')  * 1;
  var half    = Math.round(Math.abs((end - start)/2));
  var middle  = Math.round((self.selectSequenceStart + self.selectSequenceEnd)/2);
  var newName = self.ref+':'+(middle-half)+'..'+(middle+half)+ ',' + self.segmentStart + ',' + self.segmentEnd;
  document.mainform.name.value = newName;
  self.clearAndSubmit();
}

// Make best effort to set the opacity of the selectbox
// background color
SelectArea.prototype.setOpacity = function(el,opc) {
  var self = currentSelectArea;

  if (!(el && opc)) return false;

  // Just an outline for Konqueror
  if (navigator.userAgent.indexOf( 'Konqueror' ) != -1) {
    YAHOO.util.Dom.setStyle(el,'border','1px solid black');
    return false;
  }

  opc = parseFloat(opc);
  YAHOO.util.Dom.setStyle(el,'background',self.background||'#BABABA');
  YAHOO.util.Dom.setStyle(el,'opacity',opc);
  YAHOO.util.Dom.setStyle(el,'filter','alpha(opacity= '+(100*opc)+')');
  YAHOO.util.Dom.setStyle(el,'MozOpacity',opc);
  YAHOO.util.Dom.setStyle(el,'KhtmlOpacity',opc);
}
