

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 
//		var: ControlCenter
//		This Class realizes the connection between the browser address bar and the status of the page. 
//		If the address changes, <Bubble>s and <Details> will be generated or deleted, stopped or resumed. 
//		Moreover it does the JSON data imports. 
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////




var ControlCenter = new Class(
{
	
	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// var: options
	// default settings
	Implements: [Options, Events],
	options: 
	{
		projectsPerPart: 7,
		minBubbleOverlap: 100,
		minBubbleRest: 30,
		minBubbleHeightRandom: 30,
		contentMargin: 10,
		contentTop: 14,
		contentHeight: 330
	},
	
		
	
	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// vars: Internal data
	// capsuled into an object named data
	// 
	// lastHash			- the previous addessbar-hash for comparison
	// part				- the actual page part
	// project			- the actual project
	// detail			- the actual project detail
	// partsCount		- the amount of parts for this page
	// allProjects		- an object with project informations inside for internal corrections
	//
	data: 
	{
		lastHash: null,
		part: null,
		project: null,
		detail: null,
		partsCount: 0,
		allProjects: {}
	},
	
	
	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// vars: Child elements
	// capsuled into an object named elements
	// 
	// bubbles			- all bubbles of this part are stored here
	// details			- the current details instance, if available
	// btnPrev			- the prev-part-button
	// btnNext			- the next-part-button
	//
	elements:
	{
		bubbles: [],
		details: null,
		btnPrev: null,
		btnNext: null
	},
	


	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// func: initialize
	// get and prepare the data for the page. 
	initialize: function(options) 
	{
		this.setOptions(options);
		this.preloader = new Preloader();
		document.body.setStyle('overflow','hidden');
		
		// collect all bubbles
		$$('.Bubble').each( function(num, index)
		{
			num.setStyle('display','none');
			num.removeClass('BubbleOver');
			var b = new Bubble({ elm:num, data:s.projects[index] });
			this.elements.bubbles.push(num);
		},this);
		this.preloader.preload( s.baseDir+'style/corner_LB_over.gif', 2 );
		this.preloader.preload( s.baseDir+'style/corner_LT_over.gif', 2 );
		this.preloader.preload( s.baseDir+'style/corner_RT_over.gif', 2 );
		this.preloader.preload( s.baseDir+'style/corner_RB_over.gif', 2 );
		
		// build parts nav
		this.data.partsCount = Math.ceil( this.elements.bubbles.length / this.options.projectsPerPart);
		if( this.data.partsCount >1)
		{
			this.elements.btnPrev = new Element( 'img', { 'class':'rollover', title:s.labels[25], src:s.baseDir+'style/btn_prevPart.png' }).inject( $('partNav')); 
			this.elements.btnNext = new Element( 'img', { 'class':'rollover', title:s.labels[24], src:s.baseDir+'style/btn_nextPart.png' }).inject( $('partNav')); 
			this.elements.btnPrev.addEvent( 'click', this.prevPart.bind(this));
			this.elements.btnNext.addEvent( 'click', this.nextPart.bind(this));
		}
		
		// rollover all so-marked images
		$$('.rollover').each( function(num)
		{
			num.addEvent( 'mouseover', function() { num.set( 'src', num.get('src').replace(/\.(...)$/,'_over.$1')); });
			num.addEvent( 'mouseout', function() { num.set( 'src', num.get('src').replace(/_down\.(...)$/,'.$1').replace(/_over\.(...)$/,'.$1')); });
			num.addEvent( 'mousedown', function() { num.set( 'src', num.get('src').replace(/_over\.(...)$/,'_down.$1')); });
			num.addEvent( 'mouseup', function() { num.set( 'src', num.get('src').replace(/_down\.(...)$/,'_over.$1')); });
			this.preloader.preload( num.get('src').replace(/\.(...)$/,'_over.$1'), 1);
			this.preloader.preload( num.get('src').replace(/\.(...)$/,'_down.$1'), 1);
			num.removeClass('rollover');
		},this);
		
		// keep care of the title display
		var topInfo = $('topInfo').fade(0.0001);
		topInfo.addEvent( 'mouseover', function() { topInfo.set('html',s['labels'][19]).fade(0.3); });
		topInfo.addEvent( 'mouseout', function() { topInfo.fade(0.0001); });
		
		// start the urlCheck period
		this.urlCheck.periodical(50, this);
				
		// rearrange the bubbles on window resize. 
		window.addEvent( 'resize', function() { this.rearrangeBubbles('resize'); }.bind(this));
	},



	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// func: urlCheck
	// Checks periodically, if the URL has changed. If it has, the change will be executed to the elements 
	// by calling <changePart>, <changeProject> or <changeDetail>.
	urlCheck: function()
	{		
		// Interpretes the URL-hash, if it changed.
		// console.log( 'ControlCenter.urlCheck()');
		if( window.location.hash!=this.data.lastHash)
		{
			this.data.lastHash = window.location.hash;
			var hash = window.location.hash.substr(1).split('/');
			
			// If there's a part, checks, if there really are that many parts.
			// Correction if necessary, otherwise adopt it. 
			var part = 0; 
			if( hash.length>0 && hash[0]==hash[0].toInt()) 
			{
				var tmpPart = hash[0].toInt();
				if( tmpPart<this.data.partsCount) part = tmpPart;
			}
			
			// If there's a project, adopt it if existant.
			// Auto-detect part.
			var project = ''; 
			var projects = $H({});
			s['projects'].each( function(num) { projects[num['dir']] = num['numSlides']; });
			if( hash.length>0 && projects[hash[0]])
			{
				project = hash[0];
				var tmpArr = projects.getKeys();
				part = Math.floor( tmpArr.indexOf(project) / this.options.projectsPerPart);
			}
			
			// If there's a slide, checks, if there really are that many slides.
			// Correction if necessary, otherwise adopt it. 
			var detail = 0;
			if( hash.length>1 && project && hash[1].toInt())
			{
				var numSlides = projects[project];
				if( hash[1].toInt()<numSlides) detail = hash[1].toInt();
			}
			
			// And, of course, if after all this verification something really has changed, 
			// apply the changes with <changePart>, <changeProject> and <changeDetail>. 
			if( part!=this.data.part ) { this.data.part = part; this.changePart(); }
			if( detail!=this.data.detail ) { this.data.detail = detail; this.changeDetail(); }
			if( project!=this.data.project ) { this.data.project = project; this.changeProject(); }
			// console.log( 'ControlCenter.urlCheck() part='+part+', project='+project+', detail='+detail);
		}
	},
	
	
	
	
	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// func: changePart
	// Every Page may contain more Projects than it can display at once. If it does, the amount of projects is splitted into parts. 
	// This function switches between those parts
	nextPart: function() { window.location.hash = '#'+(this.data.part+1)+'/'; },
	prevPart: function() { window.location.hash = '#'+(this.data.part-1)+'/'; },
	changePart: function()
	{
		// console.log( 'ControlCenter.changePart()');
		
		// by making the actual <Bubble>s disappear 
		this.elements.bubbles.each( function(num) { num.fade('hide').setStyles({display:'none', left:'200px'}).freeze(); });
		
		// and showing other <Bubble>s. 
		var o = this.options;
		var d = this.data;
		var e = this.elements;
		var count = 0;
		for( var i=d.part*o.projectsPerPart; i<(d.part+1)*o.projectsPerPart; i++)
		{
			count += 1;
			if( e.bubbles[i]) e.bubbles[i].start(150*count);
		}
		
		// take care of the parts navigation (more/back) visibility
		if( d.partsCount >1)
		{
			if( d.part >0) e.btnPrev.set('href','#'+(d.part-1)).setStyle('display','inline').fade('in'); 
			else this.elements.btnPrev.setStyle('display','none').fade('hide');
			if( d.part < d.partsCount-1) e.btnNext.set('href','#'+(this.data.part+1)).setStyle('display','inline').fade('in'); 
			else this.elements.btnNext.setStyle('display','none').fade('hide');
		}
		
		// bubble positioning 
		this.rearrangeBubbles('new');
	},



	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// func: changeProject
	// This opens or closes the big <Details>-Bubble. 
	changeProject: function()
	{
		// console.log( 'ControlCenter.changeProject()' );
		var o = this.options;
		var d = this.data;
		var e = this.elements;
		
		// First of all close existant <Details> instances, if present. 
		if( e.details ) 
		{
			if( e.details.disappear ) e.details.disappear(); 
			e.details = null; 
			// and clear the <Preloader>-queue
			$('Preloader').queue = [];
			this.preloader.empty();
		}
		
		// If there's no new project <Details>, <resume> all the <Bubble>s. 
		if( !d.project ) 
		{
			for( var i=d.part*o.projectsPerPart; i<(d.part+1)*o.projectsPerPart; i++)
			{
				if( e.bubbles[i]) e.bubbles[i].start(0);
			}
		}
		
		// Otherwise freeze all <Bubble>s, hide the one, whose details will be shown
		else 
		{
			var w, h, x, y;
			this.elements.bubbles.each( function(num,i)
			{
				if( num.options.detailsLink=='#'+this.data.project+'/' ) 
				{
					var coords = num.getCoordinates();
					x = coords.left;
					y = coords.top;
					w = coords.width;
					h = coords.height;
					num.fade('hide');
					// console.log( 'hiding bubble '+i );
				}
				num.freeze();
			},this);
			
			// and create a new <Details> instance, 
			this.elements.details = new Details({ startW:w, startH:h, startX:x, startY:y, page:s.page, part:this.data.part, project:this.data.project, activeItem:this.data.detail });
		}
	},
	


	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// func: changeDetail
	// This switches the items within the big <Details>-Bubble, if a details-Bubble exists. 
	changeDetail: function()
	{
		// console.log( 'ControlCenter.changeDetail()');
		if( this.elements.details) this.elements.details.showItem(this.data.detail);
	},



	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// func: rearrangeBubbles
	// This function realizes the positioning of the <Bubble>s. 
	rearrangeBubbles: function(type)
	{
		var o = this.options;
		var d = this.data;
		var e = this.elements;
		var sizes = [];
		for( var i=d.part*o.projectsPerPart; i<(d.part+1)*o.projectsPerPart; i++)
		{
			if( e.bubbles[i]) 
				sizes.push({ w:e.bubbles[i].options.w, h:e.bubbles[i].options.h, y:e.bubbles[i].getStyle('top').toInt() });
		}
		
		// calculate minimal distances
		var x = o.contentMargin.toInt();
		sizes.each( function(num,i)
		{
			if( i>0)
			{
				var prevW = sizes[i-1].w;
				if( prevW > num.w ) x = x + prevW - num.w + o.minBubbleRest;
				else x = x + o.minBubbleRest;
			}
			var minY = 0;
			var maxY = o.minBubbleHeightRandom; // if( num.h+o.minBubbleHeightRandom < o.contentHeight) maxY = o.contentHeight - size.h; 
			var y = num.y; if( y==0 ) y = $random( minY, maxY) + o.contentTop;
			sizes[i].x = x;
			sizes[i].y = y;
		},this);
		
		// if some space left then, expand distances
		var maxContentWidth = $('pageBox').getSize().x - 2 * this.options.contentMargin;
		var contentWidth = x;  if( sizes.length >0) contentWidth = x + sizes[sizes.length-1].w;
		if( contentWidth < maxContentWidth)
		{
			var contentWidthDiff = maxContentWidth - contentWidth;
			var contentWidthDiffPart = Math.floor(contentWidthDiff / (this.options.projectsPerPart -1));
			sizes.each( function(num,i)
			{
				var correctedX = num.x + contentWidthDiffPart * (i);
				if( i>0 )
				{
					var maxX = sizes[i-1].x + sizes[i-1].w - this.options.minBubbleOverlap;
					if( correctedX > maxX ) { correctedX = maxX; }
				}
				num.x = correctedX;
			}, this);
		}
		
		// apply new position to the <Bubbles>
		var count = 0;
		for( var i=d.part*o.projectsPerPart; i<(d.part+1)*o.projectsPerPart; i++)
		{
			if( e.bubbles[i])
			{
				if( type=='new') e.bubbles[i].setStyles({ left:sizes[count].x, top:sizes[count].y });
				else e.bubbles[i].morph({ left:sizes[count].x, top:sizes[count].y });
			}
			count += 1;
		}		
	}
});











