Effect.Bounce = Class.create();
Object.extend(Object.extend(Effect.Bounce.prototype, Effect.Base.prototype), {
  initialize: function(element) {
    this.element = $(element);
    var options = Object.extend({
		x:0, y:200,
		acceleration: 9.81,
		transition: Effect.Transitions.linear,
		mode: 'relative'
    }, arguments[1] || {});
    this.start(options);
  },
  setup: function() {
    Element.makePositioned(this.element);
    this.originalLeft = parseFloat(Element.getStyle(this.element,'left') || '0');
    this.originalTop  = parseFloat(Element.getStyle(this.element,'top')  || '0');
    if(this.options.mode == 'absolute') {
      this.options.x = this.options.x - this.originalLeft;
    }
  },
  mytransition: function(pos){
    //var temp = (pos < 0.5 ? 0.5-pos : 0.5+(1-pos);
	//return (pos < 0.5 ? 9.81/2*pos*pos : 9.81/2*(1-pos)*(1-pos) ) *8 /9.81;
	var temp = (pos < 0.5 ? 0.5-pos : 0.5+(1-pos)); 
	return (pos < 0.5 ? this.options.acceleration/2*temp*temp : this.options.acceleration/2*(1-temp)*(1-temp) ) *8 /this.options.acceleration - 1;
  },
  update: function(position) {
    Element.setStyle(this.element, {
        left: this.options.x  * position + this.originalLeft + 'px',
	top:  this.originalTop + this.options.y * this.mytransition(position)   + 'px'
    });
  }
});

var BounceController = Class.create();
BounceController.prototype = {
	initialize: function(element){
		this.element = $(element);
		this.options = Object.extend({
			height: 150,
			disappearAfter: 5
		}, arguments[1]||{});
		this.nextX = false;
		this.stopOnNext = false;
		this.stopped = true;
		this.emptyCount = 0;
		this.nextQueue = [];
		Element.hide(this.element);
	},
	start: function() { 
		this.stopped = false;
		new Effect.Appear(this.element, { duration: 0.5, delay: 0.5 });
		this.stopOnNext = false;
		this.next(); 
	},
	stop: function() { 
		this.stopOnNext = true;
	},
	setStopped: function(){
		this.stopped = true;
	},
	next: function(){
		var nextStep = this.next.bind(this);
		if(this.stopOnNext){
			nextStep = this.setStopped.bind(this);
			new Effect.Fade(this.element, {duration: 0.5});
		}
		if(this.nextX){
			new Effect.Bounce(this.element, {mode: 'absolute', y: this.options.height, x: this.nextX, afterFinish: nextStep});
			this.setNextFromQueue();
		} else {
			new Effect.Bounce(this.element, {y: this.options.height, x: 0, afterFinish: nextStep});
			if(!this.setNextFromQueue())
				if(this.emptyCount++ >= this.options.disappearAfter) this.stop();
		}
	},
	setNextFromQueue: function(){
		if(this.nextQueue.length > 0){
			 this.nextX = this.nextQueue.pop();
			 return true;
		}else{
			this.nextX = false;
			return false;
		}
	},
	addToQueue: function(xPos){
		if(typeof xPos == 'object'){
			this.nextQueue = [this.nextQueue, xPos].flatten();
		} else {
			this.nextQueue.push(xPos);
		}
	},
	setNext: function(xPos){
		this.nextX = parseFloat(xPos);
		this.nextQueue = [];
		this.emptyCount = 0;
		if(this.stopped){
			Element.setStyle(this.element, {left: (xPos||0) + 'px'});
			this.start();
		}
	}
}