if( typeof Prototype === 'undefined' ) { throw("image_zoom.js requires Prototype.js library"); }

var ZoomableImage = Class.create({
 
 initialize: function(image) {
  this.stepIn		= 35 / 100;
  this.stepOut		= 50 / 100;
  this.zoomFactor	= 4.5;

  this.image = image;


  this.origWidth = this.image.getWidth();
  this.origHeight = this.image.getHeight();
  this.origMargin = this.image.getStyle('margin');
  this.actWidth = this.image.getWidth();
  this.actHeight = this.image.getHeight();

  // Fix parents hight to prevent jumping
  var parentBlock = this.image.up();
  while(parentBlock.getStyle('display') != 'block'){
   parentBlock = parentBlock.up();
  }
  parentBlock.setStyle(
   {
    'height': parentBlock.getHeight() + 'px',
    'width': parentBlock.getWidth() + 'px'
   }
  );

  this.isZooming = false;
  this.isZoomedIn = false;
  this.zoomRequest = false;
  this.zoomRequestRunning = false;
  this.zoomRequestWaitEnd = false;
  this.dir = '';
  this.pe = null;
  this.peRequest = null;
  this.sSrc = image.readAttribute('src');
  this.bSrc = this.sSrc.replace(/\/small\//, '/medium/');
  //'/fotos/profil/medium/' + this.userID + '.jpg';*/

  pos = this.image.positionedOffset();
  this.center = [ pos[0] + this.image.getWidth() / 2, pos[1] + this.image.getHeight() / 2 ];
 },

 doZoomIn: function() {
  this.isZoomedIn = true;
  this.actWidth += this.origWidth * this.stepIn;
  this.actHeight += this.origHeight * this.stepIn;
  this.image.setStyle(
   {
    'width':	this.actWidth + 'px',
    'height':	this.actHeight + 'px',
    'left':	Math.floor(this.center[0] - this.actWidth / 2) + 'px',
    'top':	Math.floor(this.center[1] - this.actHeight / 2) + 'px'
   }
  );
  if( this.actWidth >= (this.origWidth * this.zoomFactor) ) {
   this.pe.stop();
   this.isZooming = false;
   this.pe = null;
   this.dir = '';
  }
 },

 doZoomOut: function() {
  this.actWidth -= this.origWidth * this.stepOut;
  this.actHeight -= this.origHeight * this.stepOut;
  this.image.setStyle(
   {
    'width':	this.actWidth + 'px',
    'height':	this.actHeight + 'px',
    'left':	Math.floor(this.center[0] - this.actWidth / 2) + 'px',
    'top':	Math.floor(this.center[1] - this.actHeight / 2) + 'px'
   }
  );
  if( this.actWidth <= this.origWidth ) {
   this.image.setStyle(
    {
     'z-index':		1,
     'position':	'static',
     'top':		0 + 'px',
     'left':		0 + 'px',
     'width':		this.origWidth + 'px',
     'height':		this.origHeight + 'px'
    }
   );
   this.zoomRequestWaitEnd = false;
   this.pe.stop();
   this.image.undoPositioned();
   this.reset();
  }
 },

 zoomRequestHandler: function() {
  if( this.zoomRequest ) {
   this.zoomRequestWaitEnd = true;
   this.zoomIn();
  }
 },

 zoomIn: function() {
  if( this.isZooming && this.dir == 'in' ) {
   return;
  }
  if( this.isZoomedIn ) {
   return;
  }
  if( !this.zoomRequest && !this.zoomRequestRunning ) {
   this.zoomRequest = true;
   this.peRequest = new PeriodicalExecuter(this.zoomRequestHandler.bind(this), 0.3);
   this.zoomRequestRunning = true;
   return;
  } else if( this.zoomRequestWaitEnd ) {
   this.peRequest.stop();
   this.peRequest = null;
   this.zoomRequestRunning = false;
  } else {
   return;
  }
  if( this.isZooming && this.dir == 'out' ) {
   this.pe.stop();
   this.pe = null;
  }
  this.isZooming = true;
  this.dir = 'in';
  this.image.makePositioned();
  this.image.setStyle(
   {
    'z-index':	999,
    'position':	'absolute',
    'left':	this.image.offsetLeft + 'px',
    'top':	this.image.offsetTop + 'px',
    'width':	this.origWidth + 'px',
    'height':	this.origHeight + 'px',
    'margin':	0
   }
  );
  this.pe = new PeriodicalExecuter(this.doZoomIn.bind(this), 0.01);
  this.image.writeAttribute('src', this.bSrc);
 },

 zoomOut: function() {
  if( this.isZooming && this.dir == 'out' ) {
   return;
  }
  if( this.zoomRequest ) {
   this.zoomRequest = false;
   this.zoomRequestRunning = false;
   this.zoomRequestWaitEnd = false;
   if( null != this.peRequest ) {
    this.image.writeAttribute('src', this.sSrc);
    this.peRequest.stop();
    this.peRequest = null;
   }
  }
  if( this.isZooming && this.dir == 'in' ) {
   this.pe.stop();
   this.isZooming = false;
   this.dir = '';
   this.pe = null;
  }
  this.isZooming = true;
  this.dir = 'out';
  this.pe = new PeriodicalExecuter(this.doZoomOut.bind(this), 0.01);
 },

 reset: function() {
  this.actWidth = this.origWidth;
  this.actHeight = this.origHeight;
  this.image.writeAttribute('src', this.sSrc);
  this.image.setStyle(
   {
    'margin': this.origMargin
   }
  );
  //this.image = null;
  this.isZooming = false;
  this.dir = '';
  this.pe = null;
  this.isZoomedIn = false;
 }
});

var ImageZoomer = Class.create({
 initialize: function(){
  this.zoomObjects = new Hash();
 },

 init: function(){
  var images = $$('img.zoomable');
  images.each(
   function(image){
    image.observe('mouseover', zoomer.zoomIn.bind(zoomer));
    image.observe('mousemove', zoomer.zoomIn.bind(zoomer));
    image.observe('mouseout', zoomer.zoomOut.bind(zoomer));
   }
  );
 },

 zoomOut: function(event){
  var id = event.element().identify();
  if( undefined == this.zoomObjects.get(id) ) {
   return false;
  } else {
   this.zoomObjects.get(id).zoomOut();
   return true;
  }
 },
 
 zoomIn: function(event){
  var id = event.element().identify();
  if( undefined == this.zoomObjects.get(id) ) {
   this.zoomObjects.set(id, new ZoomableImage(event.element()));
  }
  this.zoomObjects.get(id).zoomIn();
  return true;
 }
});

var zoomer = new ImageZoomer();
Ajax.Responders.register({
 onComplete: zoomer.init
});

document.observe("dom:loaded", zoomer.init);

