/*


88888888888               888             d8b             88888888888          888888b.            
    888                   888             Y8P                 888              888  "88b           
    888                   888                                 888              888  .88P           
    888   .d88b.      .d88888  .d88b.     888 .d8888b         888   .d88b.     8888888K.   .d88b.  
    888  d88""88b    d88" 888 d88""88b    888 88K             888  d88""88b    888  "Y88b d8P  Y8b 
    888  888  888    888  888 888  888    888 "Y8888b.        888  888  888    888    888 88888888 
    888  Y88..88P    Y88b 888 Y88..88P    888      X88        888  Y88..88P    888   d88P Y8b.     
    888   "Y88P"      "Y88888  "Y88P"     888  88888P'        888   "Y88P"     8888888P"   "Y8888  

																   Box-Grid Handler v. 1.09 beta
																by TODO Interaction & media design
														   http://www.todo.to.it | just@todo.to.it
*/

///////////////////////////////////////////////////////
//// the Coord Class
//////////////////////////////////////////////////////

var Coord = new Class ({
	initialize: function(top, left) {
		this.top = top;
		this.left = left;
		this.taken = false;
		this.fx = $empty;
		this.scroll = $empty;
	}
});


///////////////////////////////////////////////////////
//// the Absolute Coord Class
////	- used to make references into the multidimensional array space
//////////////////////////////////////////////////////

var AbsCoord = new Class ({
	initialize: function(row, col) {
		this.row = row;
		this.col = col;
	}
});


///////////////////////////////////////////////////////
//// boxReset Class
////	- Reset all the boxes dimension to the default
//////////////////////////////////////////////////////
var boxReset = new Class({
	Implements: [Events, Options],
	
	options: {
		/*
		onComplete: $empty;
		*/
	},
	
	initialize: function(options) {
		this.setOptions(options);
		mySelf = this;
	},
	
	resetAll: function(doTheSet) {
		var flat_cords = self.coords.flatten();
		self._elements.each(function(item, index){
			if(item.getWidth() > self.min_w)
			{
				self.addLog("resetAll():: _elements[" + self._elements.indexOf(item) + "]");
				ids = self._elements[self._elements.indexOf(item)].getElements('input');
				var BoxRequest = new Request.HTML({
						url:'getBoxContent.php',
						onRequest: function() {
							item.set('html', '');
							item.set('html', '<div class=\'loadingtext\'>loading...</div>');
						},
						update: item,
						onComplete:function(html)
						{
							abscoords = self.getAbsCoord(index);
							item.setStyle('display', 'none');
							/*
							self.coords[abscoords.row][abscoords.col].fx.start({
							    'width': [item.getWidth() - item.getStyle('margin-right').toInt(), self.min_w - item.getStyle('margin-right').toInt()],
							    'height': [item.getHeight() - item.getStyle('margin-bottom').toInt(), self.min_h - (item.getStyle('margin-right').toInt())]
							}); */
							item.setStyle('width', self.min_w - item.getStyle('margin-right').toInt());
							item.setStyle('height', self.min_h - (item.getStyle('margin-right').toInt()));
							item.setStyle('display', 'block');
							if(doTheSet)
							{
								self.oneIsSelected = "";
								untaken = new PositionUntaken({
									onDone: function() {
										item.set('class', 'box');
										$('projectcontainer').setStyle('height', (flat_cords[self._elements.length-1].top+self.min_h));
										mySelf.done();
									}
								});
								untaken.position(self.coords, -1);
							} else {
								item.set('class', 'box');
								self.oneIsSelected = "";
								$('projectcontainer').setStyle('height', (flat_cords[self._elements.length-1].top+self.min_h));
								mySelf.done();
							}
						}
					}).get({'id': ids[1].value, 'mode':'off'});
			}
		});
	},
	
	done: function() {
		self.addLog("resetAll()::completed");
		this.fireEvent('done');
	}
});

///////////////////////////////////////////////////////
////  takenSetter Class
////	- Allocate the grid coords that are going to be taken by the enlarging box
//////////////////////////////////////////////////////
var takenSetter = new Class({
	Implements: [Events, Options],
	
	options: {
		/*
		onComplete: $empty;
		*/
	},
	
	initialize: function(options) {
		this.setOptions(options);
		mySelf = this;
	},

	setTaken: function(startCoord, height, width, newcoords) {
		self.addLog("setTaken():: end_row: "+ ((startCoord.top/self.min_h) + height) + "\nend_col: "+ ((startCoord.left/self.min_w) + width) );
		self.takencoords = new Array();
		rel_row = 0;
		rel_col = 0;
		buf = "";
		for(row = (startCoord.top/self.min_h); row < ((startCoord.top/self.min_h) + height); row++)
		{
			self.takencoords[rel_row] = new Array();
			for(col=(startCoord.left/self.min_w); col < ((startCoord.left/self.min_w) + width); col++)
			{
				buf += "[ " + row + ":" + col + " ], ";
				newcoords[row][col].taken = true;
				self.takencoords[rel_row][rel_col] = newcoords[row][col];
				rel_col ++;
			}
			rel_row ++;
		}
		this.done();
		self.addLog("processed" + buf);
		self.addLog("setTaken():: ..done!");
		return  newcoords;
	},
	
	done: function() {
		this.fireEvent('done');
	}
});


///////////////////////////////////////////////////////
//// Once u have set the taken coords u can position all the other boxes
//////////////////////////////////////////////////////

var PositionUntaken = new Class({
	Implements: [Events, Options],
	
	options: {
		/*
		onComplete: $empty;
		*/
	},
	
	initialize: function(options) {
		this.setOptions(options);
		mySelf = this;
	},
	
	initialize: function(options) { this.setOptions(options); },
	
	position: function(takecoords, skipidx)
	{
		self.addLog("positionUntaken()::" + "coord.left:" + self.takencoords[0][0].left + "coords.top:" + self.takencoords[0][0].top);
		var els = $('projectcontainer').getElements('div.box');
		coords_flat = takecoords.flatten();
		n = 0;
		var skipel = $empty;
	
		if(skipidx >= 0)
		{
			skipel = els[skipidx];
			els.splice(skipidx, 1);
			try {
				skipel.setStyle('top', self.takencoords[0][0].top);
				skipel.setStyle('left', self.takencoords[0][0].left);
			} catch(ex) { self.addLog("positionUntaken():: <b>ERROR</b>&raquo;&raquo;" + ex.toString())}
		}

		for(i = 0; i < coords_flat.length; i++)
		{
			if(n < els.length)
			{
				if( (!coords_flat[i].taken))
				{
					els[n].setStyle('top', coords_flat[i].top);
					els[n].setStyle('left', coords_flat[i].left);
					n++;
					self.lastCoord = coords_flat[i];
				}
			} else {
//				self.addLog("positionUntaken() :: setted proj box container height on " + $('projectcontainer').getStyle('height') );
				delete els;
				this.done();
				return true;
			}
		}
		delete els;
		this.done();
		return false;
	},
	
	done: function() {
		this.fireEvent('done');
	}
});


// superglobalz
var self;

var BoxInit = new Class({

		Implements: [Events, Options],
		
		options: {
			DEBUG: false, // turns on/off debug output -- needs to have a copule of div in da index page.
			logbox: 'logger',
			nworks: 0
		},

		///////////////////////////////////////////////////////
		//// Init
		//////////////////////////////////////////////////////		
  		initialize: function(options) {
			this.setOptions(options);
			self = this;
			this.coords = new Array();
			this.min_w = $empty;
			this.min_h = $empty;
			this.takencoords = new Array();
			this._elements = $empty;
			this.lastCoord = $empty;
			this.oneIsSelected = $empty;
			this.mfx = $empty;
			this.creditsslide = $empty;
			this.mySelf = $empty;
			this.released = true; // tell if a box opening is still running
	
			this._elements = $('projectcontainer').getElements('div.box');
			this.min_w = this._elements[0].getStyle('width').toInt() + this._elements[0].getStyle('margin-right').toInt();
			this.min_h = this._elements[0].getStyle('height').toInt() + this._elements[0].getStyle('margin-bottom').toInt();

			this.addLog("setting up min_w: " + this._elements[0].getStyle('width').toInt() + "+ " + this._elements[0].getStyle('margin-right').toInt() + " | min_h: " + this._elements[0].getStyle('height').toInt() + " + " + this._elements[0].getStyle('margin-bottom').toInt());

			this.allocateCoords(options.nworks);

			if(options.DEBUG)
				$('clearlog').addEvent('click', function() { $('logger').set('html', 'Logger:<br/><br/>'); } );

			var flat_cords = this.coords.flatten();
			this.addLog("seting up initial grid");
			for(i=0; i < this._elements.length; i++)
			{
				this.addLog("Setting positions: left: " + flat_cords[i].left + " | top: " + flat_cords[i].top) ;
				this._elements[i].setStyle('left', flat_cords[i].left);
				this._elements[i].setStyle('top', flat_cords[i].top);
				abscoords = this.getAbsCoord(i);
				this.addLog("el init: \n" + row  +  " | " + col );
				this.coords[abscoords.row][abscoords.col].fx = new Fx.Morph( this._elements[i], {duration: 1, transition: Fx.Transitions.Sine.easeOut});
				this.coords[abscoords.row][abscoords.col].scroll = new Fx.Scroll( $(document.body), {
						wait: false,
						duration: 700,
						wheelStops: false,
						offset: {'x': 0, 'y': - (this._elements[i].getStyle('margin-bottom').toInt()) },
						transition: Fx.Transitions.Quad.easeInOut
					});
			}
			this.addLog('.... done!');
			//$('projectcontainer').setStyle('height', (this.min_h*(nworks/5)));
//			alert(flat_cords[this._elements.length-1].top);
			$('projectcontainer').setStyle('height', (flat_cords[this._elements.length-1].top+this.min_h));
			this._elements.each(function(item, index)
			{
				item.addEvents({
					'click': function(e) {
						if( (e != null) && (e != $empty) )
						e.stop();
						if( (self.oneIsSelected != item) && (self.released))
						{
							self.released = false;
							self.addLog("box Clicked: id="+index);
							abscoords = self.getAbsCoord(index);
							switch(abscoords.col)
							{
								case 0: // those one from the 1st column
										self.boxSetup(item, abscoords.row, abscoords.col, index);
										//boxSetup()
										break;								
								case 1: // those one form the 2nd col
										self.boxSetup(item, abscoords.row, abscoords.col, index);
										break;
								case 2:
										self.boxSetup(item, abscoords.row, abscoords.col, index);
										break;
								case 3: // those are from the 4th col
										self.boxSetup(item, (abscoords.row), 2, index);
										break;
								case 4: // 5th column
										self.boxSetup(item, (abscoords.row), 2, index);
										break;
							}
						}
					},

					'mouseenter': function(e) {
						e.stop();
						tmp_els = $("projectcontainer").getElements('div.box'); // cuz $unlink didn't work out.
						tmp_els.splice(tmp_els.indexOf(item), 1);
						self.addLog("fading:: index: " + index + " | selectedId: " + tmp_els.indexOf(self.oneIsSelected));
						if( (tmp_els[tmp_els.indexOf(self.oneIsSelected)] != item) && ( tmp_els.indexOf(self.oneIsSelected) >= 0) )
							tmp_els.splice(tmp_els.indexOf(self.oneIsSelected), 1);
						tmp_els.set('tween', { duration:50 }).fade('0.6');
						item.set('tween', { duration:50 }).fade('1');
						delete tmp_els;
					},						

					'mouseleave': function(e) {
						e.stop();
						self._elements.each(function(itm, index) { itm.fade("in"); });
//						self._elements.fade("in");
					}
				}); // eof - item.addEvents()
			}); // eof - each()
			//});
		},
				
		///////////////////////////////////////////////////////
		//// EOF Init vars
		//////////////////////////////////////////////////////
		
		getAbsCoord: function(index) {
			col = (index % 5);
			row = (index/5).toInt();
			return new AbsCoord(row, col);
		},
		
		//////////////////////////////////////////////////////
		//// LOGGING FUNCTION
		//////////////////////////////////////////////////////
		addLog: function(what) {
			if(this.options.DEBUG)
				$(this.options.logbox).set('html', $(this.options.logbox).get('html') + what +  "<br />");
		},
		
		///////////////////////////////////////////////////////
		//// Creates the multi dimensional array containing the grid choords
		//////////////////////////////////////////////////////
		
		allocateCoords: function( maxrows )
		{
			this.addLog("allocateCoords("+maxrows+")");	
			col = 0;
			for(row = 0; row < maxrows; row ++ )
			{
				this.coords[row] = new Array();
				for(col = 0; col < 5; col ++)
				{
					this.coords[row][col] = new Coord((row*this.min_h), (col*this.min_w)); // top, left
				}
			}
		},
		
		
		///////////////////////////////////////////////////////
		//// Sets the height of the container in order to riposition the footer in coincidence of the end of the last box
		//////////////////////////////////////////////////////
	 	getContainerHeight: function() {
			this.addLog("resizing main proj content box's height");
			var tmp_takencoords = this.takencoords.flatten();
			if( (tmp_takencoords[tmp_takencoords.length-1].top >= this.lastCoord.top) ) {//|| ( (this.oneIsSelected != "") && (this.oneIsSelected != $empty) ) ) {
//				alert("wins" + (tmp_takencoords[tmp_takencoords.length-1].top + this.min_h) + " | loses: " + (this.lastCoord.top+this.min_h));
				return tmp_takencoords[tmp_takencoords.length-1].top + this.min_h;
			} else {
				return this.lastCoord.top+this.min_h;
			}
		},
			
		///////////////////////////////////////////////////////
		//// One the box has shown (& loaded) this funct enables controls
		//////////////////////////////////////////////////////
		setBoxControls: function(item) {
			var slideshow = new BarackSlideshow('menu', 'pictures', 'loading', { transition: 'fade', auto: false, tween: 700, startindex: 0 });
			$('next').addEvent('click', function(ev){ ev.stop(); slideshow.next(); });
			$('prev').addEvent('click', function(ev){ ev.stop(); slideshow.prev(); });

			$('closebox').addEvent('click', function (ev){
				ev.stop();
				reset = new boxReset({
					onDone: function() {
						this.released = true;
					}
				});
				reset.resetAll(true);
				
				// reset url
				cur_url = window.document.location.toString();
				cur_url = cur_url.substring(0, cur_url.lastIndexOf("#")); // removes all the stuff after the / -- e.g. /persol --> /
				window.document.location.href = cur_url + "#projects";
			});
			$('pictures').addEvent('click', function (ev){ ev.stop(); slideshow.next(); });

			creditsslide = "a";
			creditsslide = $empty;
			delete creditsslide;

			if($('creditscontent') != null)
			{
		        creditsslide = new Fx.Slide($('creditscontent'), { transition: 'sine:out', open:false, duration: 500 }).hide();
		           $('creditstoggle').addEvent('click', function(e){
		            e.stop();
		           creditsslide.toggle();
		           });
			}
			item.getElement('div.boxlink').getElements('a').each(function(itm, idx) {
				itm.addEvent('click', function() {
					if( (itm.getProperty('href') != "") && (itm.getProperty('href') != "#") )
						window.open(itm.getProperty('href'));
				});
			});
			
			item.getElement('div.boxtext').getElements('a').each(function(itm, idx) {
				itm.addEvent('click', function() {
					if( (itm.getProperty('href') != "") && (itm.getProperty('href') != "#") )
						window.open(itm.getProperty('href'));
				});
			});
		},
		
		///////////////////////////////////////////////////////
		///// A simple utiliy to fade in the selected project when the box opens
		///////////////////////////////////////////////////////		
		fadeSelected: function(item, index) 
		{

			try {
				tmp_els = $("projectcontainer").getElements('div.box'); // cuz $unlink didn't work out.
				tmp_els.splice(tmp_els.indexOf(item), 1);
				//self.addLog("fading:: index: " + index + " | selectedId: " + tmp_els.indexOf(self.oneIsSelected));
				if( (tmp_els[tmp_els.indexOf(self.oneIsSelected)] != item) && ( tmp_els.indexOf(self.oneIsSelected) >= 0) )
				{
					tmp_els.splice(tmp_els.indexOf(self.oneIsSelected), 1);
				}
				tmp_els.fade('0.6');
				item.set('tween', { duration:700 }).fade('1');
				delete tmp_els;
			} catch(ex) { /* catch that bitch! */ }
		},
		
		///////////////////////////////////////////////////////
		///// Setting up box element for expanding and grid reallign
		///////////////////////////////////////////////////////
		boxSetup: function(item, row, col, index) {
				this.addLog("boxSetup():: row: " + row + " | col: " + col + " | index: " + index );
				ids = item.getElements('input');
				element_id = ids[1].value;
				// url substitution
				cur_url = window.document.location.toString();
//					cur_url = cur_url.substring(0, cur_url.lastIndexOf("/")); // removes all the stuff after the / -- e.g. /persol --> /
					if(cur_url.indexOf('#') > 0)
						cur_url = cur_url.substring(0, cur_url.indexOf('#'));
					else if(cur_url.indexOf('project') > 0)
							cur_url = cur_url.substring(0, cur_url.indexOf('project'));
					cur_url += "#projects/" + ids[2].value;
					window.document.location.href = cur_url;
				// -eof- substritution
				var BoxRequest = new Request.HTML({
					url:'getBoxContent.php',
					onRequest: function() {
						item.set('html', '');
						item.set('html', '<div id="loadmask"></div>');
					},
					update: item,
					onComplete:function(html)
					{
						target_h = item.getElements('div')[0].getHeight();
						target_w = (self.min_w * 3) - item.getStyle('margin-right').toInt();
						// arround height

						var target_h = ((self.min_h) * ( Math.ceil(target_h/self.min_h).round() ) ) - (item.getStyle('margin-bottom').toInt());// bug height
						var tmp_coords = $unlink(self.coords);
							setter = new takenSetter({
								onDone: function() {
									if( (self.oneIsSelected != "") && (self.oneIsSelected != $empty) ) 
									{ 
										self.addLog("one box selected");
										item.getElement("div").getElement('div').setStyle("display", "block");
										tmp_selectedItem = self.oneIsSelected;
										tmp_selectedItem.setStyle('overflow', 'hidden');
										item.setStyle('overflow', 'hidden');
										reset = new boxReset({
											onDone: function() {
												item.getElement("div").getElement('div').setStyle("display", "none");
												self.addLog("resetAll()::done! ");
												tmp_selectedItem.setStyle('display', 'none');
												item.setStyle('display', 'block'); // et, voila' the box has shown again
							   					item.set('class', 'box boxactive');
												tmp_selectedItem.setStyle('overflow', 'visible');
												untaken = new PositionUntaken({
													onDone: function() {
														item.setStyle('overflow', 'visible');
														item.setStyle('width', target_w);
														item.setStyle('height', target_h);
														tmp_selectedItem.setStyle('display', 'block');	
														self.oneIsSelected = item;
														$('projectcontainer').setStyle('height', self.getContainerHeight());
														self.coords[abscoords.row][abscoords.col].scroll.toElement(item);
														self.fadeSelected(item, index);
														self.setBoxControls(item);
														self.released = true;
													}
												});
												untaken.position(tmp_coords, (index));
											}
										});
										reset.resetAll(false);
									} else {
										untaken = new PositionUntaken({
											onDone: function() {
												item.setStyle('display', 'block'); // et, voila' the box has shown again
							   					item.set('class', 'box boxactive');
												self.oneIsSelected = item;
												abscoords = self.getAbsCoord(index);
												item.setStyle('width', target_w);
												item.setStyle('height', target_h);
												$('projectcontainer').setStyle('height', self.getContainerHeight());
												self.coords[abscoords.row][abscoords.col].scroll.toElement(item);
												self.fadeSelected(item, index);
												self.setBoxControls(item);
												self.released = true;
												item.getElement("div.boxbody").setStyle('visibility', 'visible');
											}
										});	
										untaken.position(tmp_coords, (index));
									}
							 	}
							});
							
							tmp_coords = setter.setTaken(self.coords[row][col], Math.ceil(target_h/self.min_h).round(), Math.ceil(target_w/self.min_w).round(), tmp_coords);
							self.addLog("boxInit()::complete!");
					}
				}).get({'id': element_id, 'mode':'on'});
		}

}); // eof class
