function BoxesController(rotator, pos) {
    var self = this;
    this.rotator = rotator;
    var Dom = YAHOO.util.Dom;
    var slides = Dom.getChildren(rotator.slidesEl);

    var boxes = document.createElement('div');
    Dom.addClass(boxes, 'boxes-controller');
    Dom.setStyle(boxes, 'display', 'none'); //hide by default
    Dom.addClass(boxes, 'boxes-controller-' + pos);
    for(var i=0;i<slides.length;i++){
	    var slide = slides[i];
	    var box = document.createElement('span');
	    var si = i;
	    Dom.addClass(box, 'boxes-controller-box');
	    if (i==0)
		    Dom.addClass(box, 'selected'); //start with first selected
	    boxes.appendChild(box);
	    YAHOO.util.Event.addListener(box, "click", function(evt, slide){
			rotator.showSlide(slide);
		}, si);
    }
    this.boxesEl = boxes;

    Dom.insertBefore(boxes, Dom.getFirstChild(rotator.id));

    rotator.onSlideChange.subscribe(function(evt, args){
		//alert(args[0]['index']);
    		var Dom = YAHOO.util.Dom;
		var boxes = Dom.getChildren(self.boxesEl);
		for(var i=0;i<boxes.length;i++){
			if(i==args[0]['index'])
				Dom.addClass(boxes[i], 'selected');
			else
				Dom.removeClass(boxes[i], 'selected');
		}
	});

    this.show = function(){ YAHOO.util.Dom.setStyle(this.boxesEl, 'display', 'block');}
    this.hide = function(){ YAHOO.util.Dom.setStyle(this.boxesEl, 'display', 'none');}
}

function Rotator(id, width, height, config){

	var self = this;
	this.config = config;
	this.id = id;
	this.running = true;
	this.width = width;
	this.height = height;
	this.currentSlide = 0;
	this.onSlideChange = new YAHOO.util.CustomEvent("onSlideChange"); 
	var Dom = YAHOO.util.Dom;
	

	if(typeof config === "undefined")
		config = {}

	this.config = config;

	if(typeof config.interval !== "undefined"){
		this.interval = config.interval;
	}else{
		this.interval = 5000; //default to 5sec
	}

	if(typeof config.effect !== "undefined"){
		this.effect = config.effect;
	}else{
		this.effect = 'fade-in';
	}

	this.slidesEl = Dom.getFirstChild(id);
	while(!Dom.hasClass(this.slidesEl, 'rotator-slides')){
		this.slidesEl = Dom.getNextSibling(this.slidesEl);
	}

	if(config.controller.match(/^boxes-/)){
		this.controller = new BoxesController(this, config.controller.split('-')[1]);
	}

	if(config.alwaysShowController && this.controller){
		this.controller.show();
	}

	this.doAnim = function (c, n, anim, fadeCurrent) {
		var Dom = YAHOO.util.Dom;

		Dom.addClass(n, "current");
		Dom.setStyle(n, "display", "block");
		Dom.setStyle(n, "z-index", 101);
		Dom.setStyle(n, 'opacity', 0);
		Dom.setStyle(c, "z-index", 100);


		var nAnim = new YAHOO.util.Anim(n, anim, 1, YAHOO.util.Easing.easeOut);
		nAnim.onComplete.subscribe(function(){
			Dom.removeClass(c, "current");
			Dom.setStyle(c, "display", "none");
		});

		if(fadeCurrent){
			var cAnim = new YAHOO.util.Anim(c, {opacity: {to:0}}, 1, YAHOO.util.Easing.easeOut);
			cAnim.animate();
		}

		nAnim.animate();
		
	}

	this.ANIM_TYPES = {
		'slide-up': function(t, c,n) {
			t.doAnim(c, n, {top: {to:0, from:self.height}, opacity: {to:1, from:1}}, true); },
		'slide-down': function(t, c,n) {
			t.doAnim(c, n, {top: {to:0, from:self.height * -1}, opacity: {to:1, from:1}}, true); },
		'slide-left': function(t, c,n) {
			t.doAnim(c, n, {left: {to:0, from:self.width}, opacity: {to:1, from:1}}, true); },
		'slide-right': function(t, c,n) {
			t.doAnim(c, n, {left: {to:0, from:self.width * -1}, opacity: {to:1, from:1}}, true); },
		'fade-in': function(t, c,n) {
			t.doAnim(c, n, {opacity: {to:1, from:0}}, true); }
	};

	this.animate = function(animType){
		var Dom = YAHOO.util.Dom;
		var func = this.ANIM_TYPES[animType];

		var i = this.currentSlide;
		var c = this.slidesEl.children[i];
		if(!c){
			c = Dom.getFirstChild(this.slidesEl);
		}


		//get next
		var n = Dom.getNextSibling(c);
		var ni = i+1;
		if(!n){
			n = Dom.getFirstChild(this.slidesEl);
			ni = 0;
		}

		func(this, c, n);
		this.currentSlide = ni;
		this.onSlideChange.fire({index: ni, el: n});
	};

	this.showSlide = function(slideIndex){
		var Dom = YAHOO.util.Dom;
		var func = this.ANIM_TYPES[this.effect];
		func(this, this.slidesEl.children[this.currentSlide], this.slidesEl.children[slideIndex]);
		this.currentSlide = slideIndex;
		this.onSlideChange.fire({index: slideIndex, el: this.slidesEl.children[slideIndex]});
	};

	this.rotate = function(){
		this.animate(this.effect);
	};

	this.loop = function(){
		if(this.running){
			this.rotate();
		}
		setTimeout(function(){self.loop();}, this.interval);
	};

	this.run = function(){
		setTimeout(this.loop, this.interval);
	};

	YAHOO.util.Event.on(id, "mouseenter", function (e) {
		self.running = false;
		if(!self.config.alwaysShowController && self.controller){
			self.controller.show();
		}
	});
	YAHOO.util.Event.on(id, "mouseleave", function (e) {
		self.running = true;
		if(!self.config.alwaysShowController && self.controller){
			self.controller.hide();
		}
	});

};


