if (typeof Prototype=='undefined')
  throw("panel.js requires the Prototype JavaScript framework >= 1.6.0");

/** Rotating Item Class 
 * @param number vX X location of the center of the menu
 * @param number vY Y Location of the center of the menu
 * @param number vRadius The radius of the circle
 * @param array vItems List of rotary_menu_item objects
 * @param integer vStartAngle Start angle of the first item. Default is 0;
 * @param array vBlankSlots List of locations (0 based) to skip in the list. Typically 1 and the last if the first item is larger
*/
var rotary_menu = Class.create();
rotary_menu.prototype = {
	DefaultOptions: {
	        x:       		0,
	        y:       		0,
	        radius:    		300,
	        rotation:   	0,
			rotationPercentage: 1, 
			items: 			Array(),
			rotationTime: 	1500, 	//Time in milliseconds
	        fadePause: 		500, 	//time to wait before fading out in slot 0 in milliseconds
			fadeUpCallback: '',
			menuReadyCallback: ''
	},
  
  	initialize: function(vX, vY, vRadius, vItems, vStartAngle, vBlankSlots, vOffsets, vMenuReadyCallback, vMenuCallback,vDuration){
		this.x = vX;
		this.y = vY;
		this.radius = vRadius;
		this.items = new Array();
		this.rotationTime = 1500;
		this.fadeInterval = 0;
		//this._options = Object.extend(Object.extend({ },this.DefaultOptions), { });
		this.duration = 1;
		if(vDuration != undefined){
		    this.duration = vDuration;
		}
		this.offsets = vOffsets;
		this.active = 0;
		this.menuCallback = vMenuCallback
		this.menuReadyCallback = vMenuReadyCallback
		if(vItems != undefined){
			//go ahead and build it out
			this.items = vItems;
		}
		//check the empty slots
		if(vBlankSlots != undefined){
			this.blankSlots = vBlankSlots;
		}else{
			vBlankSlots = Array();
		}
		if(vStartAngle == undefined){
			this.startAngle = 0;
		}else{
			this.startAngle = vStartAngle;
		}
		this.rebuild();
		this.fadeInterval = this.puffMe();//setTimeout(this.puffMe.bindAsEventListener(this), 100);
	}, 
	
	animate: function(){
		//clear it first
		if(this.interval != 0 && this.interval != undefined){
			return;
		}
		this.active = 1;
		//if we are waiting for a fade, stop it
		this.clearFadeInterval();
		
		//see if we have a fade waiting
		if(this.fadeInterval != undefined && this.fadeInterval != 0){
			//remove it
			clearInterval(this.fadeInterval);
		}
		
		var d = new Date();
		this.startTime = d.getTime();
		//set it up
		this.interval = setInterval(this.animateStep.bindAsEventListener(this), 50);
		this.showAll();
	},
	
	freeze: function(){
		clearInterval(this.interval);
		this.interval = 0;
		//puff delay
		this.fadeInterval = this.puffMe();//setTimeout(this.puff, 1500, this)
	},
	
	animateStep: function(){
		//get the difference
		var d = new Date();
		dif = d.getTime() - this.startTime;
		this.rotationPercentage = Math.min(1, dif / this.rotationTime);
		this.displayPositions();
		if(this.rotationPercentage >= 1){
			this.freeze();			
		}
	},
	//Rebuild/redraw the item
 	rebuild: function(){
		//current rotation percentage (0-1)
		this.rotationPercentage = 1;	
		//calculate the slots
		this.calculateSlots();
		//get the angle
		this.getAngle();
		//draw them
		this.setInitialLocations()
	},
	
	//Calculate the angle between items
	getAngle: function(){
		this.angle = 360/this.availableSlots.length;
	},
	//Gets the angle for a specific slot
	//returns the angle for the slot
	getSlotAngle: function(iCurrent){
		angle = this.startAngle + (this.angle * iCurrent)
		return angle;
	},
	
	//Get the list of available slots
	calculateSlots: function(){
		var iTotal = this.items.length;
		if(this.blankSlots.length > 0){	
			iTotal = iTotal + this.blankSlots.length;
			for(i=0;i<this.blankSlots.length;i++){
				iTotal = Math.max(iTotal, this.blankSlots[i] + 1);
			}
		}
		this.availableSlots = Array();
		for(i=0;i<iTotal;i++){
			this.availableSlots[this.availableSlots.length] = 1;
		}
		if(this.blankSlots.length > 0){
			for(i=0;i<this.blankSlots.length;i++){
				v = this.blankSlots[i];
				this.availableSlots[v] = 0;
			}
		}	
	},

	//changes the items used
	changeItems: function(vItems){
		//set the items
		this.items = vItems;
		this.initialize();
	},
	
	//sets the initial location for the items
	setInitialLocations: function(){
		var iCurrent = 0;
		this.rotationPercentage = 1;
		for(i=0;i<this.items.length;i++){
			//find an ok slot
			while(this.availableSlots[iCurrent]==0){
				iCurrent ++;			
				if(iCurrent >= this.availableSlots.length){
					//error, bail
					return;
				}
			}		
			var iItem = this.items[i];
			//set the location
			iItem.slot = iCurrent;
			//set start and end to the same
			iItem.startAngle = this.getSlotAngle(iCurrent);
			iItem.endAngle = iItem.startAngle;
			//increment
			iCurrent ++;
		}	
		this.displayPositions();
	},

	displayPositions: function(){
		//go through each
		for(s=0;s<this.items.length;s++){
			var iItem = this.items[s];
			var angle = ((iItem.endAngle - iItem.startAngle) * this.rotationPercentage) + iItem.startAngle;
			//get the point
			var iX = Math.round(this.radius * Math.cos(angle * Math.PI / 180));
			var iY = Math.round(this.radius * Math.sin(angle * Math.PI / 180));
			iItem.setPosition(iX + this.x, iY + this.y);
		}
	},
	
	nextRotation: function(){
		//go to the next item
		this.advanceRotation(1);
		
	},
	
	prevRotation: function(){
		//go to the previous item
		this.advanceRotation(-1);
	},
	jumpTo:function(vNum){
		//get the current item in slot 0
		var current = 0;
		var numSlots = this.items.length;
		for(j=0;j<this.items.length;j++){
			iItem = this.items[j];
			if(iItem.slot == 0){
				current = j;
			}
		}
		//get the difference
		d = current - vNum;
		if(d==0){
			return;
		}
		//start forward
		if(d < 0){
		    d = d + numSlots;
		}
		if((this.items.length / 2) < Math.abs(d)){		
	    	d = d - numSlots;
		}
		
		//roll it
		if(d == 0){
			return;
		}
		this.advanceRotation(d);
	},
	advanceRotation: function(vDirection){
		//bail if already in process...
		if(this.interval != 0 && this.interval != undefined){
			return;
		}
		
		var n = Math.abs(vDirection);
		var d = vDirection / n;
			
		for(j=0;j<this.items.length;j++){
			var iItem = this.items[j];
			for(i=1;i<=n;i++){
				iItem.slot = this.findAllowedSlot(iItem.slot, d);
			}
			iItem.startAngle = iItem.endAngle;
			if(iItem.startAngle > 360){
				iItem.startAngle = iItem.startAngle - 360;
			}
			if(iItem.startAngle < 0){
				iItem.startAngle = iItem.startAngle + 360;
			}
			iItem.endAngle = this.getSlotAngle(iItem.slot);
			//unify the direction for multiples
			if(n>1){
				if(d > 0){
					//forward
					if(iItem.endAngle < iItem.startAngle){
						iItem.endAngle = iItem.endAngle + 360;
					}
				}else{
					if(iItem.endAngle > iItem.startAngle){
						iItem.endAngle = iItem.endAngle - 360;
					}
				}
			}
			//check direction
			iDiff = iItem.endAngle - iItem.startAngle;
			if(iDiff / Math.abs(iDiff) != d){
				//wrong way
				if(vDirection == 1){
					iItem.endAngle = iItem.endAngle + 360;
				}else{
					iItem.endAngle = iItem.endAngle - 360;					
				}
			}
		}
		this.rotationPercentage = 0;
		this.animate();
	},
	
	findAllowedSlot: function(vSlot, vDirection){
		iCurrent = vSlot + vDirection;
		last = this.availableSlots.length - 1;
		while(iCurrent != vSlot){
			if(this.availableSlots[iCurrent] == 1){
				return iCurrent;
			}
			iCurrent = iCurrent + vDirection;
			if(iCurrent > last){
				iCurrent = 0;
			}		
			if(iCurrent < 0){
				iCurrent = last;
			}
		}
		
	},
	
	puffMe:function(){
		if(this.clearFadeInterval != undefined){
		    this.clearFadeInterval();
		}
		this.active = 0;
		var a = this;
		var myItems = this.items;
		myItems.each(function(item){
		
		//for(pSlot=0;pSlot<s;pSlot++){
		//    var item;
		//    item = this.items[pSlot];
			if(item.slot == 0){
				//done, call the callback
				a.callMenuCallback(item.id);
				item.puffOut();
			}
		//}
		})
	}, 
	//unpuff
	unpuff:function(){
		if(this.clearFadeInterval != undefined){
		    this.clearFadeInterval();
		}
		a = this;
		
		this.items.each(function(item){
		//for(uSlot=0;uSlot<this.items.size();uSlot++){
		//    item = this.items[uSlot];
			if(item.slot == 0){
				//done, call the callback
				item.puffIn(a.menuReadyCallback);
			}
		//}
		})
		
	},
	
	showAll: function(){	
		//this.items.each(function(item){
		for(sSlot=0;sSlot<this.items.length;sSlot++){
		    var item = this.items[sSlot];
			item.forceIn();
		//})
		}
		
	},
	
	clearFadeInterval: function(){
		if(this.fadeInterval != undefined && this.fadeInterval > 0){
			clearTimeout(this.fadeInterval);
			this.fadeInterval = 0;
		}
	},
	//sets the callback
	setMenuCallback: function(vCallback){
		this.menuCallback = vCallback;
	},
	callMenuCallback: function(id){
		if(this.menuCallback != undefined){
			//get the correct item
			this.menuCallback(id);
		}
	},
	//sets the callback
	setMenuReadyCallback: function(vCallback){
		this.menuReadyCallback = vCallback;
	},
	callMenuReadyCallback: function(id){
		if(this.menuCallback != undefined){
			//get the correct item
			this.menuReadyCallback(id);
		}
	}
}

/** Individual item for a menu 
 * @param string filePath Path to the image file
 * @param string id Unique id for callbacks
*/
var rotary_menu_item = Class.create();
rotary_menu_item.prototype = {
	DefaultOptions: {
		filePath: "",
		id: "",
		startAngle: 0,
		endAngle: 0,
		containerWidth : 0,
		containerHeight : 0,
		x: -1000,
		y: -1000
	},
	
	initialize: function(filePath, id){
		this.duration = 1;
		this.filePath = filePath;
		this.id = id;
		this._options = Object.extend(Object.extend({ },this.DefaultOptions), { });
		this.containerWidth = 0;
		this.containerHeight = 0;
		
		//create the div
		this.container = Builder.node('div',{ 'id':this.id+'_outer', 'class':'rotary_menu_item', 'style':'position:absolute;display:none'});
		o = $('outer_base');
		o.appendChild(this.container);
		//create the image inside
		this.icon = Builder.node('img',{ 'id':this.id+'_image', 'class':'rotary_menu_item_image', 'style':'', 'src' : this.filePath});
		this.container.appendChild(this.icon);	
		
		//observe a click
		Event.observe(this.container, 'click', this.itemClicked.bindAsEventListener(this));
	},

	setPosition: function(vX, vY){
		//get the offset position based on the width and height
		this.setDimensions();
		this.x = Math.round(vX - this.containerWidth / 2);
		this.y = Math.round(vY - this.containerHeight / 2);
		//actually move it
		$(this.container).setStyle({'left':this.x + "px", 'top':this.y + "px", 'position':'absolute', 'display' : 'block'});
	},
	
	//force it back on just in case
	forceIn: function(){
	    this.setDimensions();
		if(this.puff != undefined){
			this.puff.cancel();
			this.puff = undefined;
		}
		$(this.container).setStyle({ 'display': 'block', 'opacity':1, 'width':this.width+'px', 'height':this.height+'px' });
		
	},
	//fades down items that are currenly up
	puffOut: function(){
		this.setDimensions();
		this.puff = new Effect.Fade(this.container.id, {duration : this.duration});
	},
	//Puff back in
	puffIn:function(vCallback){
		$(this.icon).setStyle({ 'display': 'block', 'width':this.width+'px', 'height':this.height+'px'});
		if(vCallback != undefined && vCallback != ''){
			force = this.forceIn.bindAsEventListener(this);
			this.puff = new Effect.Appear(this.container.id, {afterFinish:function(){force();vCallback()}, duration: this.duration});
		}else{
			this.puff = new Effect.Appear(this.container.id, {duration : this.duration});	
		}
	},
	itemClicked:function(){
		//call out to the page to do the rotation
		doRotation(this.id);
		
	},
	setDimensions:function(){
	    if(this.containerWidth <= 0 || this.containerWidth == undefined){
			this.containerWidth = $(this.container).getWidth();
			this.containerHeight = $(this.container).getHeight();
		}
		if(this.width == undefined || this.width <= 0){
		    var img = $(this.icon);
		    var dim = img.getDimensions();
			this.width = dim.width;
			this.height = dim.height;
		}
	}
}

/** Content area system
 * Handles the content area
*/
var content_area = Class.create();
content_area.prototype = {
	DefaultOptions:{
		width: 1000,
	 	height: 525,
		top: 265,
		left: 800,
		rows: 2,
		cols: 3,
		active: false
	},
	//initialize
	initialize: function(vId){
		//store the values
		this.id = vId;
		this.container = $(vId);
		this.duration = 1;
		this.width = this.container.getWidth();
		this.height = this.container.getHeight();
		this.top = this.container.getStyle('top');
		this.left = this.container.getStyle('left');
		this.active = false;
		this.hideContent(1);
	},

	//show the menu
	showContent: function(vNow){
		this.active = true;
		this.stopGrow();
		if(vNow == true){
			$(this.container).setStyle({'height' : this.height + 'px', 'width' : this.width + 'px', 'top' : this.top, 'left': this.left, 'position':'absolute'});
		}else{
			this.growEffect = new Effect.Appear(this.container.id, {duration : this.duration});
		}
	},
	//Hide it
	hideContent: function(vNow){
			this.stopGrow();
			this.active = false;
			if(vNow == true){
				$(this.container).setStyle({'display' : 'none', 'height' : this.height + 'px', 'width' : this.width + 'px', 'top' : this.top, 'left': this.left, 'position' : 'absolute'});
			}else{
				this.growEffect = new Effect.Fade(this.container.id, {duration : this.duration});
			}
			
	},
	//stops the grow effect
	stopGrow: function(){
		if(this.growEffect != undefined){
			this.growEffect.cancel();
			this.growEffect = undefined;
		}		
	}
}
