BannerController = Base.extend({
   banners: new Array (),
   index:   0,
   current: null,
   
   initialize: function () {
   },
   
   add: function (banner) {
      this.banners.push (banner);
      banner.init ();
      banner.controller = this;
   },
   
   rotate: function () {
      var pauseTime = this.current.pauseTime;
      this.current.stop ();
      this.current.reset ();
      this.index++;
      this.index %= this.banners.length;
      this.current = this.banners[this.index];
      setTimeout (this.current.start.bind (this.current), pauseTime);
   },
   
   start: function () {
      if (this.banners.length > 0) {
         if (!this.current) {
            this.index = Math.floor (Math.random () * this.banners.length);
            this.current = this.banners[this.index];
         }
         this.current.start ();
      }
   },
   
   stop: function () {
      if (this.current) {
         this.current.stop ();
      }
   },
   
   restart: function () {
      if (this.banners.length > 0 && this.current) {
         this.current.stop ();
         this.current.reset ();
         this.current.start ();
      }
   },
   
   clear: function () {
      this.stop ();
      while (this.banners.length) {
         this.banners[0].destroy ();
         this.banners.shift ();
      }
      this.index   = 0;
      this.current = null;
   }
});


BannerBase = Base.extend({
   controller: null,
   timer: new Array (),
   element: null,
   interval: 50,
   speed: 1,
   pauseTime: 2000,
   halfway: false,
   
   constructor: function (element, speed, pauseTime) {
      this.element  = element;
      if (speed) {
         this.speed = parseInt (speed);
      }
      if (pauseTime) {
         this.pauseTime = parseInt (pauseTime);
      }
   },
   
   init: function () {
      this.text = '';
      while (this.element.childNodes.length > 0) {
         var c = this.element.removeChild (this.element.firstChild);
         
         if ( c.nodeType == 3 ) {
            this.text += c.nodeValue.replace (/\r?\n/g, '\r');
         } else if ( c.nodeType == 1 && c.tagName.toLowerCase() == 'br' ) {
            this.text += '\r';
            if (!document.all) {
               this.text += '\n';
            }
         }
      }
      this.element.appendChild (document.createTextNode(this.text));
   },
   
   update: function () {
   },
   
   reset: function () {
   },

   start: function () {
      this.timer = setInterval (this.update.bind (this), this.interval);
   },
   
   stop: function () {
      if (this.timer) {
         clearTimeout (this.timer);
      }
   },
   
   pause: function () {
      this.stop ();
      setTimeout (this.start.bind (this), this.pauseTime);
   },
   
   destroy: function () {
      this.stop ();
      delete this.controller;
      delete this.timer;
      delete this.element;
      delete this.interval;
      delete this.speed;
      delete this.pauseTime;
      delete this.halfway;
   }
});


ScrollBanner = BannerBase.extend ({
   update: function () {
      if (!this.element || !this.element.parentNode) {
         return;
      }
      this.element.style.left = px(this.element.offsetLeft + this.speed * -1);
      if (!this.halfway && Math.floor (this.element.parentNode.offsetWidth / 2 - this.element.offsetWidth / 2 - this.element.offsetLeft) > 0) {
         this.halfway = true;
         this.pause ();
      }
      if (this.element.offsetLeft < this.element.offsetWidth * -1) {
         this.controller.rotate ();
      }
   },
   
   reset: function () {
      this.halfway = false;
      this.element.style.left = px(this.element.parentNode.offsetWidth);
   }
});


HeadlineBanner = BannerBase.extend ({
   update: function () {
      if (!this.element || !this.element.parentNode) {
         return;
      }
      this.element.style.top = px(this.element.offsetTop + this.speed * -1);
      if (!this.halfway && Math.floor (this.element.parentNode.offsetHeight / 2 - this.element.offsetHeight / 2 - this.element.offsetTop) > 0) {
         this.element.style.top = px(Math.floor (this.element.parentNode.offsetHeight / 2 - this.element.offsetHeight / 2));
         this.halfway = true;
         this.pause ();
      }
      if (this.element.offsetTop < this.element.offsetHeight * -1) {
         this.controller.rotate ();
      }
   },
   
   reset: function () {
      this.halfway = false;
      this.element.style.top = px(this.element.parentNode.offsetHeight);
   }
});


FadeBanner = BannerBase.extend ({
   opacity: 0,
   
   update: function () {
      if (!this.element || !this.element.parentNode) {
         return;
      }
      this.element.style.top = px(Math.floor (this.element.parentNode.offsetHeight / 2 - this.element.offsetHeight / 2));
      this.opacity = Math.max (0, Math.min(this.opacity + (0.03 * (this.halfway ? -1 : 1)), 1));
      Element.setOpacity (this.element, this.opacity);
      if (!this.halfway && this.opacity >= 1) {
         this.halfway = true;
         this.pause ();
      } else if (this.halfway && this.opacity <= 0) {
         this.controller.rotate ();
      }
   },
   
   reset: function () {
      this.halfway = false;
      this.opacity = 0;
      Element.setOpacity (this.element, 0);
   }
});


TypewriterBanner = BannerBase.extend ({
	text: null,
	len: 0,
	done: false,
	
	init: function () {
		if (this.text == null) {
   		this.text = '';
			while (this.element.childNodes.length > 0) {
            var c = this.element.removeChild (this.element.firstChild);
            
            if ( c.nodeType == 3 ) {
               this.text += c.nodeValue.replace (/\r?\n/g, '\r');
            } else if ( c.nodeType == 1 && c.tagName.toLowerCase() == 'br' ) {
               this.text += '\r';
               if (!document.all) {
                  this.text += '\n';
               }
            }
            this.text = this.text.replace (/\r\r+/g, '\r');
			}
			this.element.appendChild (document.createTextNode(' '));
		}
	},
	
	update: function () {
      if (!this.element || !this.element.parentNode) {
         return;
      }
		this.element.firstChild.nodeValue = this.text.substring (0, Math.min (this.text.length, this.len));
		
		if (this.len >= this.text.length && !this.done) {
			this.done = true;
			this.pause ();
		} else if (this.len >= this.text.length) {
			this.done = false;
         this.controller.rotate ();
		}
		this.len += this.speed;
	},
	
	reset: function () {
		this.element.firstChild.nodeValue = '';
		this.len = 0;
	}
});


Typewriter2Banner = TypewriterBanner.extend ({
	update: function () {
      if (!this.element || !this.element.parentNode) {
         return;
      }
		this.element.firstChild.nodeValue = this.text.substring (Math.min (this.text.length, this.text.length - this.len));
		
		if (this.len >= this.text.length && !this.done) {
			this.done = true;
			this.pause ();
		} else if (this.len >= this.text.length) {
			this.done = false;
         this.controller.rotate ();
		}
		
		this.len += this.speed;
	}
});

