/* Image cube manager. */
function ImageCube() {
	this._defaults = {
		nextStepCallback: null,
		speed: 2000, // Time taken (milliseconds) to transition
		easing: 'linear', // Name of the easing to use during transitions
		repeat: true, // True to automatically trigger a new transition after a pause
		selection: 'forward', 
		pause: 2000, // Time (milliseconds) between transitions
		opacity: [0.0, 0.8], // Minimum/maximum opacity (0.0 - 1.0) for highlights and shadows
		lineHeight: [0.0, 1.25], // Hidden and normal line height (em) for text
		letterSpacing: [-0.4, 0.0] // Hidden and normal letter spacing (em) for text
	};
};

var UP = 0;
var DOWN = 1;
var LEFT = 2;
var RIGHT = 3;

var PROP_NAME = 'imageCube';

$.extend(ImageCube.prototype, {
	/* Class name added to elements to indicate already configured with image cube. */
	markerClassName: 'hasImageCube',

	/* Override the default settings for all image cube instances.
	   @param  options  object - the new settings to use as defaults */
	setDefaults: function(options) {
		extendRemove(this._defaults, options || {});
	},

	/* Attach the image cube functionality to a div.
	   @param  target   element - the containing division
	   @param  options  object - the settings for this image cube instance (optional) */
	_attachImageCube: function(target, options) {
		target = $(target);
		if (target.is('.' + this.markerClassName)) {
			return;
		}
		target.addClass(this.markerClassName);
		var allOptions = $.extend({}, this._defaults, options || {});
		$.data(target[0], PROP_NAME, allOptions);
		target.children().each(function() {
			var child = $(this);
			$.data(this, PROP_NAME,
				{width: child.css('width'), height: child.css('height'),
				position: child.css('position'), lineHeight: child.css('lineHeight'),
				letterSpacing: child.css('letterSpacing')});
			child.css({width: target.css('width'), height: target.css('height'),
				position: 'absolute', lineHeight: allOptions.lineHeight[1],
				letterSpacing: allOptions.letterSpacing[1]});
		}).not(':first').hide();
		this._prepareRotation(target[0]);
	},
	
	_runCallback: function (target) {
		target = $(target);
		var options = $.data(target[0], PROP_NAME);
		if(options.nextStepCallback != null)
		{
			var sNext = "";
			switch(options.nextStepCallback)
			{
				// 1 3 2 4 
				case 'ob_1':
					sStop = 'ob_4';
					break;
					
				case 'ob_2':
					sStop = 'ob_3';
					break;
					
				case 'ob_3':
					sStop = 'ob_1';
					break;
					
				case 'ob_4':
					sStop = 'ob_2';
					break;
			}

			var oObjStop = $('#'+sStop);
			
			oObjStop.children('img').css("z-index", "0");
			
			$('#'+options.nextStepCallback).imagecube('start'); 			
			oObjStop.imagecube('stop');
		}
	},
	
	/* Note current visible child and schedule a repeat rotation (if required).
	   @param  target  element - the containing division */
	_prepareRotation: function(target) {
		target = $(target);
		var options = $.data(target[0], PROP_NAME);
		options.current = target.children(':visible')[0];
		if (options.repeat && !options._timer) {
			if (!target[0].id) {
				target[0].id = 'ic' + new Date().getTime();
			}
			options._timer = setTimeout('jQuery.imagecube._rotateImageCube("#' +	target[0].id + '")', options.pause);
		}
		$.data(target[0], PROP_NAME, options);
	},

	/* Rotate the image cube to the next face.
	   @param  target    element - the containing division
	   @param  callback  function - a function to call when finished with the rotation (optional) */
	_rotateImageCube: function(target, callback) {
		target = $(target);
		this._stopImageCube(target[0], true);
		var options = $.data(target[0], PROP_NAME);
		var animTo = {};
		animTo[PROP_NAME] = 1.0;
		
		target.attr(PROP_NAME, 0.0).animate(animTo, options.speed, options.easing, callback);
	},

	/* Retrieve the currently visible child of an image cube div.
	   @param  target  element - the containing division
	   @return  element - the currently displayed child of target division */
	_currentImageCube: function(target) {
		return $.data(target, PROP_NAME).current;
	},

	/* Stop the image cube automatically rotating to the next face.
	   @param  target     element - the containing division
	   @param  timerOnly  boolean - true if only temporarily stopping (optional) */
	_stopImageCube: function(target, timerOnly) {
		var options = $.data(target, PROP_NAME);
		if (options._timer) {
			clearTimeout(options._timer);
			options._timer = null;
		}
		if (!timerOnly) {
			options.repeat = false;
		}
		$.data(target, PROP_NAME, options);
	},

	/* Start the image cube automatically rotating to the next face.
	   @param  target  element - the containing division */
	_startImageCube: function(target) {
		this._changeImageCube(target, {repeat: true});
	},

	/* Reconfigure the settings for an image cube div.
	   @param  target   element - the containing division
	   @param  options  object - the new settings for this image cube instance */
	_changeImageCube: function(target, options) {
		var curOptions = $.data(target, PROP_NAME);
		extendRemove(curOptions || {}, options || {});
		$.data(target, PROP_NAME, curOptions);
		this._prepareRotation(target);
	},

	/* Remove the image cube functionality from a div.
	   @param  target  element - the containing division */
	_destroyImageCube: function(target) {
		this._stopImageCube(target);
		target = $(target);
		if (!target.is('.' + this.markerClassName)) {
			return;
		}
		target.stop().removeClass(this.markerClassName).
			children('.imageCubeShading').remove();
		target.children().each(function() {
			$(this).css($.data(this, PROP_NAME)).show();
			$.removeData(this, PROP_NAME);
		});
		$.removeData(target[0], PROP_NAME);
	},

	/* Prepare the image cube for animation.
	   @param  target  element - the containing division */
	_prepareImageCube: function(target) 
	{
		var options = $.data(target, PROP_NAME);
		var target = $(target);
		var isFixed = false;
		var randomSelection = function(collection) {
			return (!collection.length ? collection : collection.filter(
				':eq(' + Math.floor(Math.random() * collection.length) + ')'));
		};
		var sObrazekPokazywany = target.children(':visible');
		var pObrazekDoPokazania = sObrazekPokazywany.next();
		pObrazekDoPokazania = (pObrazekDoPokazania.length ? pObrazekDoPokazania : target.children(':first')); 

		// Cycle around if at the end
		var offset = target.offset();
		
		// Check if this area is fixed
		target.parents().each(function() 
		{ 
			var $this = $(this);
			if ($this.css('position') == 'fixed') {
				offset.left -= $this.offset().left;
				offset.top -= $this.offset().top;
				return false;
			}
		});
		
		var parentDiv = $('#kontener_na_img');
		var parentDivWymiary = {width: parentDiv.width(), height: parentDiv.height()};
		var parentDivOffset = parentDiv.offset();
		var szerokoscObrazka = $(pObrazekDoPokazania).width();
		var startPoint = parentDivOffset.left + parentDivWymiary.width - szerokoscObrazka;
		
		// wymiery celu :)
		var dims = {width: target.width(), height: target.height()};

		var stepProps = [];
		stepProps[0] = {elem: sObrazekPokazywany, // wyswietlany element
			left: {start: offset.left, end: offset.left, units: 'px'},
			width: {start: dims.width, end: dims.width, units: 'px'},
			opacity: {start: 0, end: 1, units: ''},
			zIndex: 0
		};

		stepProps[1] = {elem: pObrazekDoPokazania, // element do wyswietlenia
			left: {start: offset.left, end: offset.left, units: 'px'},
			width: {start: dims.width,	end: dims.width, units: 'px'},
			opacity: {start: 0, end: 1, units: ''},
			zIndex: 1000
		};

		var initCSS = function(props) {
			return {
				left: props.left.start + 'px', 
				width: props.width.start + 'px'
				//zIndex: props.zIndex
			};
		};

		sObrazekPokazywany.css(initCSS(stepProps[0])).hide();
		pObrazekDoPokazania.css(initCSS(stepProps[1])).show();

		for (var i = 0; i < stepProps.length; i++) 
		{
			for (var name in stepProps[i]) 
			{
				var prop = stepProps[i][name];
				prop.diff = prop.end - prop.start;
				//alert(prop.diff);
			}
		}
		return stepProps;
	}
});

/* jQuery extend now ignores nulls! */
function extendRemove(target, props) {
	$.extend(target, props);
	for (var name in props) {
		if (props[name] == null) {
			target[name] = null;
		}
	}
	return target;
}

/* Attach the image cube functionality to a jQuery selection.
   @param  command  string - the command to run (optional, default 'attach')
   @param  options  object - the new settings to use for these image cube instances
   @return  jQuery object - for chaining further calls */
$.fn.imagecube = function(options) {
	var otherArgs = Array.prototype.slice.call(arguments, 1);
	if (options == 'current') 
	{
		return $.imagecube['_' + options + 'ImageCube'].apply($.imagecube, [this[0]].concat(otherArgs));
	}
	return this.each(function() 
	{
		if (typeof options == 'string') 
		{
			$.imagecube['_' + options + 'ImageCube'].apply($.imagecube, [this].concat(otherArgs));
		}
		else 
		{
			$.imagecube._attachImageCube(this, options);
		}
	});
};

/*  @param  fx  object - instancja animacji */
$.fx.step[PROP_NAME] = function(fx) 
{
	// fx.state - stan w jakim znajduje sie obrazek 0 - start, 1 - koniec
	// jesli jest to pierwsze uruchomienie
	if (fx.state == 0) 
	{ 
		fx.start = 0.0;
		fx.end = 1.0;
		
		// przygotowanie animacji
		fx.stepProps = $.imagecube._prepareImageCube(fx.elem);
		
		//fx.stepProps[0].elem.show();
		fx.saveCSS = {
			borderLeftWidth: fx.stepProps[0].elem.css('borderLeftWidth'),
			borderRightWidth: fx.stepProps[0].elem.css('borderRightWidth'),
			borderTopWidth: fx.stepProps[0].elem.css('borderTopWidth'),
			borderBottomWidth: fx.stepProps[0].elem.css('borderBottomWidth'),
			padding: fx.stepProps[0].elem.css('padding')
		};
	}
	
	for (var i = 0; i < fx.stepProps.length; i++) 
	{ 
		var newValues = {};
		for (var name in fx.stepProps[i]) 
		{
			var prop = fx.stepProps[i][name];
			if (name != 'elem') 
			{
				newValues[name] = (fx.pos * prop.diff + prop.start) + prop.units;
			}
		}
		fx.stepProps[i].elem.css(newValues);
	}
	
	// jesli jest to kolejne
	if (fx.state == 1) 
	{ 
		fx.stepProps[0].elem.hide().css(fx.saveCSS);
		if (fx.stepProps.length > 2) 
		{
			fx.stepProps[2].elem.remove();
			fx.stepProps[3].elem.remove();
		}
		// uruchomienie animacji
		$.imagecube._prepareRotation(fx.elem);
		// wyzwolenie nastepnej animacji
		$.imagecube._runCallback(fx.elem);
	}
};

$.imagecube = new ImageCube();
