Effect2 = {}

Effect2.Transitions = {}
Effect2.Transitions.linear = function(pos) {
  return pos;
}

Effect2.Base = function() {};
Effect2.Base.prototype = {
  setOptions: function(options) {
    this.options = {
      transition: Effect2.Transitions.sinoidal,
      duration:   1.0,   // seconds
      fps:        25.0,  // max. 100fps
      sync:       false, // true for combining
      from:       0.0,
      to:         1.0
    }.extend(options || {});
  },
  start: function(options) {
    this.setOptions(options || {});
    this.currentFrame    = 0;
	  this.startOn  = new Date().getTime();
	  this.finishOn = this.startOn + (this.options.duration*1000);
	  if(this.options.beforeStart) this.options.beforeStart(this);
    if(!this.options.sync) this.loop();	
  },
  loop: function() {
	 timePos = new Date().getTime();
	 if(timePos >= this.finishOn) {
		this.render(this.options.to);
		if(this.finish) this.finish(); 
		if(this.options.afterFinish) this.options.afterFinish(this);
		return;	
	 }
	 pos   = (timePos - this.startOn) / (this.finishOn - this.startOn);
	 frame = Math.round(pos * this.options.fps * this.options.duration);
	 if(frame > this.currentFrame) {
		this.render(pos);
		this.currentFrame = frame;
	 }
	 this.timeout = setTimeout(this.loop.bind(this), 10);
  },
  render: function(pos) {
	 if(this.options.transition) pos = this.options.transition(pos);
	 pos  = pos * (this.options.to-this.options.from);
     pos += this.options.from; 
	 if(this.options.beforeUpdate) this.options.beforeUpdate(this);
	 if(this.update) this.update(pos);
	 if(this.options.afterUpdate) this.options.afterUpdate(this);	
  },
  cancel: function() {
	 if(this.timeout) clearTimeout(this.timeout);
  }
}

Effect2.Parallel = Class.create();
Effect2.Parallel.prototype = (new Effect2.Base()).extend({
  initialize: function(effects) {
    this.effects = effects || [];
	 this.start(arguments[1]);
  },
  update: function(position) {
	 for (var i = 0; i < this.effects.length; i++)
		this.effects[i].render(position);	
  },
  finish: function(position) {
	 for (var i = 0; i < this.effects.length; i++)
		if(this.effects[i].finish) this.effects[i].finish(position);
  }
});

Effect2.Opacity = Class.create();
Effect2.Opacity.prototype = (new Effect2.Base()).extend({
  initialize: function() {
    this.element = $(arguments[0] || document.rootElement);
    options = {
      from: 0.0,
      to:   1.0
	}.extend(arguments[1] || {});
	this.start(options);
  },
  update: function(position) {
	this.setOpacity(position);
  }, 
  setOpacity: function(opacity) {
	opacity = (opacity == 1) ? 0.99999 : opacity;
	this.element.style.opacity = opacity;
	this.element.style.filter = "alpha(opacity:"+opacity*100+")";
  }
});

Effect2.Fade =	function(element) {
  options = {
	from: 1.0,
	to:   0.0,
	afterFinish: function(effect) 
	  { Element.hide(effect.element);
	    effect.setOpacity(1); } 
	}.extend(arguments[1] || {});
  new Effect2.Opacity(element,options);
}

Effect2.Appear =	function(element) {
  options = {
	 from: 0.0,
	 to:   1.0,
	 beforeStart: function(effect)  
	   { effect.setOpacity(0);
		   Element.show(effect.element); },
	 afterUpdate: function(effect)  
	   { Element.show(effect.element); }
  }.extend(arguments[1] || {});
  new Effect2.Opacity(element,options);
}

Effect2.CrossFade = Class.create();
Effect2.CrossFade.prototype = (new Effect2.Base()).extend({
  initialize: function() {
    this.element = $(arguments[0] || document.rootElement)
    options = {
      from: 1.0,
      to:   0.0,
      duration:   2.0,   // seconds
      afterFinish: function(effect)
        {
	  var s1 = 'url(' + effect.element.getAttribute('src') + ')';
	  var s2 = effect.element.parentNode.style.backgroundImage;
	  s2 = s2.substring(4, s2.length - 1);
	  effect.element.setAttribute('src', s2);
	  effect.element.parentNode.style.backgroundImage = s1;
	  effect.setOpacity(1);
        }
      }.extend(arguments[1] || {});
    this.start(options);
  },
  update: function(position) {
    this.setOpacity(position);
  }, 
  setOpacity: function(opacity) {
    opacity = (opacity == 1) ? 0.99999 : opacity;
    this.element.style.opacity = opacity;
    this.element.style.filter = "alpha(opacity:"+opacity*100+")";
  }
});

