var Slideshow = Class.create();
Slideshow.prototype = {
	initialize: function( options) {
    this.photos = new Array();
    this.loadeds = new Array();
    this.last_request;
    this.last_request_index = 0;
    this.alternateThumbails = new Array();
    this.current = 0;
    this.options = Object.extend({
			canvas_id : 'slide_canvas',
			over_canvas : false,
			elem : 'thumbs',
			alernate : false,
			previmg : 'previmg',
			nextimg : 'nextimg',
			foot: 'slide_foot',
			title_foot: 'slide_foot_title',
			arrowClassOver : 'arrow_class_over',
			currentThumbClass : 'current_photo',
			duration: .2,
			withThumbs: false,
			numbers: false,
			dissableRightButton: false,
			numbers_text: "#1 / #2",
			counter: 'counter',
			indicator: 'slide_indicator',
			indicator_change_style: true,
			slideshow_class : 'slideshow_canvas',
			str_foot_function: false,
			autoLoad: false,
			buttons: true,
			loop: false,
			interval: 2,
			numbers: false,
			evalTitle: false,
			transition: 'fade',
			player_stop: false,
			player_play: false,
			player_start: false,
			keys: true
		}, options || {});
    
    if( this.options.over_canvas == false)
      this.options.over_canvas = this.options.canvas_id;
    
    Event.observe( document, 'keydown', this.keys.bindAsEventListener( this), false);
    
		this.createElems();
    this.getThumbs();
    this.change( this, 0);
    this.setButtons(this, 0);
    this.is_start = false;
	},
	
	createElems: function () {
	  this.createCanvas();
	  if( this.options.withThumbs == false)
      $(this.options.elem).hide();
	},
	
	setCounter: function () {
	  if( $(this.options.counter)) {
      $(this.options.counter).innerHTML = (this.current + 1) ;
      $(this.options.counter).innerHTML += " / ";
      $(this.options.counter).innerHTML += this.total + 1;
    }
	},
	
	createCanvas: function () {
	  this.canvas = document.createElement('div');
	  this.canvas.id = 'slideshow_canvas';
	  this.canvas.className = this.options.slideshow_class;
	  $(this.options.canvas_id).insert( { top: this.canvas });
	  this.createImage();
    // this.canvas.style.position = 'absolute';
	},
	
	createImage: function() {
	  this.image = document.createElement('img');
	  $(this.canvas).insert( { top: this.image });
	  if( this.options.dissableRightButton)
	    this.image.oncontextmenu = function() { return false };
	},
	
	appendImage: function( e, current) {
	  if( $(this.loadeds [current])) {
	    if( this.options.transition == 'move') {
	      this.move( this, current);
	    } else if( this.options.transition == 'fade') {
	      new Effect.Fade( this.last_request, {duration: this.options.duration});
	      this.fade( this, current);
	    }
	    this.loada( this);
  	  return false;  	  
	  }
    if( $(this.options.indicator))
      $(this.options.indicator).show();
	  var img = document.createElement('img');
	  if( this.options.dissableRightButton)
	    img.oncontextmenu = function() { return false };
	  setTimeout(this.loadAppendImage.bindAsEventListener( this, img, current), .01 * 1000);
	  
	  if( this.options.transition == 'move') {
	    img.style.position = 'absolute';
  	  img.style.left = this.calculateLeft( current) + 'px';
	  } else if( this.options.transition == 'fade') {
      Element.hide( img);
	  }

	  for( var i = current; i >= 0; i--)
	    if( $(this.loadeds [i])) {
	      $(this.loadeds [i]).insert( { after: img });
	      break;
	    }
    Event.observe( img, 'load', this.afterLoad.bindAsEventListener( this, img, current), false);
    	  
	},
	
	afterLoad: function( e, img, current) {
	  this.loadeds [current] = img;
	  if( this.options.transition == 'move') {
      this.recalculateLeft( this, current);
      this.loada( this, current)
    } else if( this.options.transition == 'fade') {
      this.fade( this, current)
    }
	},
	
	setLastRequest: function( current) {
	  this.last_request = this.loadeds [current];
	  this.last_request_index = current;
	},
	
	loadAppendImage: function( e, img, current) {
	  img.src = this.photos [current].href;
	},
	
	calculateLeft: function ( current) {	  
	  lft = 0;
	  for( var i = current; i >= 0; i--) {  	  
	     if( $(this.loadeds [i])) {
	       lft += $(this.loadeds [i]).getWidth();
	     }
	   }
	  return lft;
	},
	
	recalculateLeft: function ( e, current) {
	  lft = 0;
	  
	  for (var i=0; i < this.photos.length; i++) {
	    if( $(this.loadeds[i])) {
        $(this.loadeds[i]).style.left = lft + 'px';       
        lft += this.loadeds[i].getWidth();
	    }
	  };
	  if( (this.last_request_index - current) > 0) {
	    this.canvas.style.left = this.unit( this.canvas.style.left) - this.loadeds [current].getWidth() + 'px';
	  }
    setTimeout(this.move.bindAsEventListener( this, current), .08 * 1000);
	  
	},
	
	unit: function( unit) {
	  return unit.replace(/px,*\)*/g,"");
	},
	
	move: function( e, current) {
	  if( $(this.options.indicator))
	    $(this.options.indicator).hide();
	  last_left = this.unit( this.last_request.style.left);
	  current_left = this.unit( this.loadeds [current].style.left);
	  diff = last_left - current_left;
    new Effect.Move(this.canvas, { x: -current_left, y: 0, mode: 'absolute', duration: this.options.duration });
    this.setLastRequest( current);
	},
	
	fade: function( e, current) {
	  for (var i=0; i < this.photos.length; i++) {
	    if( $( this.loadeds[i]))
	      if( this.loadeds[i] != this.last_request && this.loadeds[i] != this.loadeds [current])
	        this.loadeds[i].hide();
	  };
    new Effect.Fade( this.last_request, {duration: this.options.duration, afterFinish: this.appear.bindAsEventListener( this, current)});
	},
	
	appear: function( e, current) {
	  this.loada( this, current);
	  new Effect.Appear( this.loadeds [current], {duration: this.options.duration, queue: 'end'});
	  this.setLastRequest( current);
    
	},
	
	getThumbs: function() {
	  var els = $$('#' + this.options.elem + ' a');

    for( var i=0; i < els.length; i++) {
      if( els[i].href) {
        els[i].onclick = function(){ return false};
        this.photos [i] = els[i];
        Event.observe( els[i], 'click', this.change.bindAsEventListener( this, i), false);
      }
    };
    this.total = els.length - 1;
    this.getAlternate();
	},
	
	getAlternate: function () {
	  if( !this.options.alternate)
	    return false;
	  var els = $$('#' + this.options.alternate + ' a');
    for( var i=0; i < els.length; i++) {
      if( els[i].href) {
        this.alternateThumbails [i] = els[i];
        Event.observe( els[i], 'click', this.change.bindAsEventListener( this, i), false);
      }
    };
	},
	
	loadImage: function(e, current) {
	  if( $(this.options.indicator))
      $(this.options.indicator).show();
    this.image.hide();
	  this.image.src = this.photos [current].href;
	  this.loadeds [current] = this.image; 
	  this.last_request = this.loadeds [current];
	  
	},
	
	change: function (e, current) {
	  if( (current == this.current && this.is_start) || (current > this.total + 1 || current < 0))
      return false;
      
	  if (this.photos [current]) {
      if( this.loadeds.length == 0) {
        setTimeout( this.loadImage.bindAsEventListener( this, current), .1 * 1000);
        Event.observe( this.image, 'load', this.loada.bindAsEventListener( this, current, true), false);
      }
      else {
        setTimeout( this.appendImage.bindAsEventListener( this, current), .1 * 1000);
      }
      this.current = current;
      this.verifyButtons();
      this.setCurrentThumbClass();
      
      if( this.options.autoLoad) {
        if( this.options.loop && this.current == this.total)
          this.current = -1;
        if( this.pe)
          this.pe.stop();
        this.pe = new PeriodicalExecuter( this.change.bindAsEventListener( this, this.current + 1), this.options.interval);
      }
	  }

	},
	
	verifyButtons: function() {
	  if( !this.options.buttons)
	    return;
	  if(!$(this.options.previmg) || !$(this.options.nextimg))
	    return;
	  if( this.current == 0)
	    $(this.options.previmg).hide();
	  else
	    $(this.options.previmg).show();
	  
	  if( this.current < this.total)
	    $(this.options.nextimg).show();
    else
      $(this.options.nextimg).hide();

    $(this.options.nextimg).onclick = function(){ return false};
    $(this.options.previmg).onclick = function(){ return false};
	},
	
	setCurrentThumbClass: function () {
    for (var i=0; i < this.photos.length; i++) {
      if( this.current == i) {
        $(this.photos[i]).addClassName( this.options.currentThumbClass);
        if( this.options.alternate && $(this.alternateThumbails[i]))
          $(this.alternateThumbails[i]).addClassName( this.options.currentThumbClass);
	   }
	   else {
	     $(this.photos[i]).removeClassName( this.options.currentThumbClass);
	     if( this.options.alternate && $(this.alternateThumbails[i]))
         $(this.alternateThumbails[i]).removeClassName( this.options.currentThumbClass)
	   }
	    
	  };
	},
	
	loada: function (e, current, first) {
	  if( first) {
	    this.afterStart();
      $(this.image).appear({duration: this.options.duration});
	  }
	  
	  this.changeDependences( current);
	  
    if( this.options.evalTitle == true && this.photos[current]) {
      eval( "titles = " + this.photos [current].rel);
      this.evalTitle( titles);
      this.evalFunction( titles);
    }
	  if( $(this.loadeds [current])) {
	    $(this.options.canvas_id).style.width = $(this.loadeds [current]).getWidth() + 'px';
      $(this.options.canvas_id).style.height = $(this.loadeds [current]).getHeight() + 'px';
      if( $(this.options.indicator) && this.options.indicator_change_style) {
        $(this.options.indicator).style.width = $(this.loadeds [current]).getWidth() + 'px';
        $(this.options.indicator).style.height = $(this.loadeds [current]).getHeight() + 'px';
      }
	  }
    this.setCounter();
    if( $(this.options.indicator))
      $(this.options.indicator).hide();
	},
	
	changeDependences: function( current)	{
	  if( this.options.evalTitle == true && this.photos[current]) {
      eval( "titles = " + this.photos [current].rel);
      this.evalTitle( titles);
      this.evalFunction( titles);
    }
    
    this.setNumbers();
	},
	
	evalTitle: function( titles) {
      // if( titles.foot)
	      this.setFoot( titles.foot);
	      this.setTitle( titles.title_foot);
	},
	
	evalFunction: function (titles) {
	    if( titles.func) {
	      eval( titles.func)
	    }
	},
	
	setFoot: function ( text) {
	  if( $(this.options.foot)) {
	    if( this.options.str_foot_function)
	      str_foot = this.options.str_foot_function( text)
	    else
	      str_foot = text;
	    $(this.options.foot).innerHTML = text;
	  }
	},
	
	setTitle: function( text)
	{
	  if( $(this.options.title_foot)) {
      $(this.options.title_foot).innerHTML = text;
    }
	},
	
	setNumbers: function() {
	  if( this.options.numbers && $(this.options.numbers)) {
      var output = this.str_replace( '#1', (this.current + 1), this.options.numbers_text);
  	  output = this.str_replace( '#2', (this.total + 1), output);
  	  $(this.options.numbers).innerHTML = output;
	  }

	},
	
	setButtons: function (e, current) {
	  if( !this.options.buttons) {
	    if( $(this.options.previmg))
	      $(this.options.previmg).hide();
      if( $(this.options.nextimg))
	      $(this.options.nextimg).hide();
	    return;
	  }
	  if( $(this.options.player_stop)) 
	     Event.observe( this.options.player_stop, 'click', this.player.bindAsEventListener( this, 'stop'), false);
    
    if( $(this.options.player_play)) 
	     Event.observe( this.options.player_play, 'click', this.player.bindAsEventListener( this, 'play'), false);
    
    if( $(this.options.player_start)) 
 	     Event.observe( this.options.player_start, 'click', this.player.bindAsEventListener( this, 'start'), false);
    
    Event.observe( this.options.previmg, 'click', this.arrows.bindAsEventListener( this, -1), false);
    Event.observe( this.options.nextimg, 'click', this.arrows.bindAsEventListener( this, 1), false);
    Event.observe( this.options.over_canvas, 'mouseover', this.setClassOver.bindAsEventListener( this), false);
    Event.observe( this.options.nextimg, 'mouseover', this.setClassOver.bindAsEventListener( this), false);
    Event.observe( this.options.previmg, 'mouseover', this.setClassOver.bindAsEventListener( this), false);
    Event.observe( this.options.canvas_id, 'mouseout', this.setClassOut.bindAsEventListener( this), false);
	},
	
	setClassOver: function () {
	  $(this.options.previmg).addClassName( this.options.arrowClassOver);
	  $(this.options.nextimg).addClassName( this.options.arrowClassOver);
	},
	
	setClassOut: function (e, div) {
	  $(this.options.previmg).removeClassName( this.options.arrowClassOver);
	  $(this.options.nextimg).removeClassName( this.options.arrowClassOver);
	},
	
	arrows: function (e, value) {
	  this.change( this, this.current + (value));
	},
	
	keys: function( e) {
	  if( this.options.keys) {
	    if( e.keyCode == 39)
  	    this.arrows( this, 1);
  	  else if( e.keyCode == 37)
  	    this.arrows( this, -1);
  	  if( e.keyCode == 39 || e.keyCode == 37)
  	  {
        // Event.stopObserving( document, 'keydown');
  	  }
	  }
	},
	
	afterStart: function() {
	  if( this.options.afterStart)
	    this.options.afterStart();
	},
	
	
	str_replace: function(busca, repla, orig) {
  	str 	= new String(orig);
  	rExp	= "/"+busca+"/g";
  	rExp	= eval(rExp);
  	newS	= String(repla);

  	str = new String(str.replace(rExp, newS));

  	return str;
  },
  
  player: function( obj, action) {
    if( action == 'stop')
      this.pe.stop();
    
    if( action == 'play')
      this.pe = new PeriodicalExecuter( this.change.bindAsEventListener( this, this.current + 1), this.options.interval);
    
    if( action == 'start') {      
      this.current = 0;
      this.change( this, 0);
    }
  }
};
