/*______________
|       ______  |   U I Z E     J A V A S C R I P T     A P I
|     /      /  |   -----------------------------------------
|    /    O /   |    MODULE : Uize.Widget.Swap Class (version 1.0.0)
|   /    / /    |    AUTHOR : Chris van Rensburg (http://www.tomkidding.com)
|  /    / /  /| |    ONLINE : http://www.tomkidding.com/uize/uize-js-api
| /____/ /__/_| | COPYRIGHT : (c)2005-2008 UIZE
|          /___ |   LICENSE : Distributed under the terms of the GNU General Public License
|_______________|             http://www.gnu.org/licenses/gpl.txt
*/

/*
	DESCRIPTION
		Implements a JavaScript class for swapping between two DIVs with dissolve support

	REQUIRES
		- Uize.Widget.js (superclass)
		- Uize.Node.js
		- Uize.Fade.js

	TO DO
		- refactor to move basic wipe code into Uize.Widget class
			- refactor various Zazzle classes that use this effect to instead use built in service
			- refactor Uize.Widget.Palette
		- handle switching transition settings during a transition (ie. make sure all state is reflected correctly visually)
		- add support for sliding new item from outside current view
*/

/*ScruncherSettings Mappings="=c" LineCompacting="TRUE"*/

Uize.module ({
	name:'Uize.Widget.Swap',
	required:[
		'Uize.Node',
		'Uize.Fade'
	],
	builder:function (_superclass) {
		/*** Variables for Scruncher Optimization ***/
			var
				_true = true,
				_false = false,
				_Uize_Node = Uize.Node
			;

		/*** Object Constructor ***/
			var
				_class = _superclass.subclass (
					function () {
						var _this = this;
						/*** Private Instance Properties ***/
							_this._viewFinalCoords = _this.viewFinalCoords = [0,0,0,0];
							_this._cycleNo = 0;

						/*** Public Instance Properties ***/
							_this.fade = new Uize.Fade ({
								duration:1250,
								acceleration:.5
							});

						/*** Initialization ***/
							_this.fade.addEventHandler (
								'Changed.value',
								function () {
									var _progress = _this.fade.get ('progress');
									if (_this._previousItem && _this._crossFade) {
										function _constrain0to1 (_value) {
											return Math.min (Math.max (_value,0),1);
										}
										var _fadeInStartPoint = (1 - _this._crossFadeSize) * _this._crossFadeAlign;
										_this._updateItem (
											_this._currentItem,
											_constrain0to1 (1 / (1 - _fadeInStartPoint) * (_progress - 1) + 1)
										);
										_this._updateItem (
											_this._previousItem,
											_constrain0to1 (1 / (_fadeInStartPoint + _this._crossFadeSize) * (0 - _progress) + 1)
										);
									} else {
										_this._updateItem (_this._currentItem,_progress);
									}
								}
							);
					}
				),
				_classPrototype = _class.prototype
			;

		/*** Private Instance Methods ***/
			_classPrototype._updateItem = function (_item,_progress) {
				var
					_this = this,
					_styleProperties = _this._dissolve ? _Uize_Node.getOpacityProperties (_progress) : {}
				;
				if (_this._viewSeedSizeX != 1 || _this._viewSeedSizeY != 1) {
					function _getViewCoord (_coordNo) {
						return (
							_this._viewSeedCoords [_coordNo] +
							(_this._viewFinalCoords [_coordNo] - _this._viewSeedCoords [_coordNo]) * _progress
						);
					}
					var
						_viewCoords = [_getViewCoord (0),_getViewCoord (1),_getViewCoord (2),_getViewCoord (3)],
						_pos = [0,0]
					;
					if (_this._viewContentAlignX !== 'none' || _this._viewContentAlignY !== 'none') {
						function _getAlignedCoord (_align,_axis) {
							function _blendValues (_value1,_value2,_blend) {return _value1 + (_value2 - _value1) * _blend}
							if (_align === 'auto')
								_align = (_this._viewSeedCoords [_axis] + _this._viewSeedCoords [_axis + 2]) / 2 / _this._viewFinalCoords [_axis + 2]
							;
							return (
								_align === 'none'
									? 0
									: _blendValues (
										_viewCoords [0 + _axis],
										_viewCoords [2 + _axis] - _this._viewFinalCoords [2 + _axis],
										_align
									)
							);
						}
						_pos [0] = _getAlignedCoord (_this._viewContentAlignX,0);
						_pos [1] = _getAlignedCoord (_this._viewContentAlignY,1);
						_styleProperties.left = _pos [0] + 'px';
						_styleProperties.top = _pos [1] + 'px';
					}
					function _getCropCoord (_coordNo) {
						return Math.round (_viewCoords [_coordNo] - _pos [_coordNo % 2] + Math.floor (_coordNo / 2)) + 'px ';
					}
					_styleProperties.clip = 'rect(' + _getCropCoord (1) + _getCropCoord (2) + _getCropCoord (3) + _getCropCoord (0) + ')';
				}
				_Uize_Node.setStyle (_item,_styleProperties);
			};

		/*** Public Instance Methods ***/
			_classPrototype.prepareForNextItem = function (_currentItem,_nextItem) {
				var
					_this = this,
					_shellNode = _this.getNode (),
					_viewFinalDims = _Uize_Node.getDimensions (_shellNode ? _shellNode : _nextItem),
					_viewFinalDimsW = _viewFinalDims.width,
					_viewFinalDimsH = _viewFinalDims.height
				;
				if (_this._cyclingPropertySets) {
					_this.set (_this._cyclingPropertySets [_this._cycleNo % _this._cyclingPropertySets.length]);
					_this._cycleNo++;
				}
				_this._viewFinalCoords [2] = _viewFinalDimsW - 1;
				_this._viewFinalCoords [3] = _viewFinalDimsH - 1;
				var
					_seedW = Math.max (0,_viewFinalDimsW * _this._viewSeedSizeX),
					_seedH = Math.max (0,_viewFinalDimsH * _this._viewSeedSizeY),
					_seedL = (_viewFinalDimsW - _seedW) * _this._viewSeedAlignX,
					_seedT = (_viewFinalDimsH - _seedH) * _this._viewSeedAlignY
				;
				_this._viewSeedCoords = [_seedL,_seedT,_seedL + _seedW - 1,_seedT + _seedH - 1];
				if (_currentItem) _this._updateItem (_currentItem,1);
				if (_nextItem) {
					if (_this._viewSeedSizeX == 1 && _this._viewSeedSizeY == 1)
						_Uize_Node.setStyle (_nextItem,0,0,_this._viewFinalCoords [2],_this._viewFinalCoords [3])
					;
					_this._updateItem (_nextItem,0);
				}
			};

			_classPrototype.setCurrentItem = function (_currentItem) {
				var _this = this;
				_this._previousItem = _this._currentItem;
				_this._currentItem = _currentItem;
				_this.fade.start ();
			};

			_classPrototype.wireUi = function () {
				this.setNodeStyle ('',{overflow:'hidden'});
				_superclass.prototype.wireUi.call (this);
			};

		/*** Setup Properties ***/
			_class.registerProperties ({
				_crossFade:{
					name:'wipeOut|crossFade',
					value:_false
				},
				_crossFadeSize:{
					name:'crossFadeSize',
					value:0
				},
				_crossFadeAlign:{
					name:'crossFadeAlign',
					value:.5
				},
				_cyclingPropertySets:'cyclingPropertySets',
				_dissolve:{
					name:'dissolve',
					value:_true
				},
				_viewContentAlignX:{
					name:'viewContentAlignX',
					value:'none'
				},
				_viewContentAlignY:{
					name:'viewContentAlignY',
					value:'none'
				},
				_viewSeedSizeX:{
					name:'viewSeedSizeX',
					value:1
				},
				_viewSeedSizeY:{
					name:'viewSeedSizeY',
					value:1
				},
				_viewSeedAlignX:{
					name:'viewSeedAlignX',
					value:.5
				},
				_viewSeedAlignY:{
					name:'viewSeedAlignY',
					value:.5
				}
			});

		return _class;
	}
});


