PA.makeNS( 'PA.widgets.scrollableGallery' );

PA.widgets.scrollableGallery = function( doc, itemsId, itemId, leftArrowId, rightArrowId, enableArrFn, disableArrFn, moveFn ) {
	var o 		= this;
	o.doc		= document;
	o.gla		= leftArrowId;
	o.gra		= rightArrowId;
	o.gis		= itemsId;
	o.gi		= itemId;	
	o.arrOn		= enableArrFn;
	o.arrOff	= disableArrFn;
	o.move		= moveFn;
	o.n			= 0;
	o.w			= 0;
	o.h			= 0;
	o._dblClick	= false;
		
	o.init = function( cb ) {
		var o							= this;
		var el	 						= o.get( o.gis );
		var gla							= o.get( o.gla );
		var gra							= o.get( o.gra );
		var n							= 0;
		if( el && gra && gla ) {
			n							= o._getNItems();	
			if( !n ) {
				return;
			}
			o.n								= n;
			o.w								= o._getItemWidth();
		
			el.style.position			= 'absolute';
			el.style.width				= o.w * parseInt( o.n ) + 'px';	// initially set to 100%	// XHTML: value must be quoted, e.g. include 'px'
			el.style.visibility 		= 'visible';		// have to initially hide it because IE shows it at first with overflowing items...
			gla.style.display			= 'block';
			gra.style.display			= 'block';

			o._prevWidth				=  el.parentNode.offsetWIdth;
			o.checkArrows( cb );
		}
	}

	o.checkArrows = function( cb ) {
		this.scroll( 0, cb );
	}
	
	o.scroll = function( dn, cb ) {	// dn = by how many items; if dn=0 just checking arrows
		var o 		= this;
		dn			= - dn;	// when we scroll "right" we in fact move div to the left
		if( !o.n || !o.get( o.gi ) || !o.get( o.gis ) ) {
			//alert( 'DOM items were not found' );
			return;
		}
		
		var x0 					= o._getCurrentOffset();		
		var dx					= o.w * ( dn ? parseInt( dn ) : 0 );	
		var x1 					= x0 + dx;		
		var overflow			= o._getOverflow();
		
		var el 					= o.get( o.gis );
		var callback			= function() { o._dblClick = false; 	if( cb ) { cb(); } };
									
		if( dx != 0 && !o._dblClick ) {
			o._dblClick			= true;
			if( x1 > 0 && dx > 0 || - x1 + dx > overflow && dx < 0 ) {
				o._dblClick		= false;
				return;
			}
			o._checkArrows( dx, x1, overflow );
			o.move( el, x0, x1, callback ); 
		} else if( 0 == dx ) {		// arrows check
			o._checkArrows( dx, x1, overflow );
			callback();
		}		
	}

	o.scrollTo = function( n, cb ) {	// note: item count starts from zero
		var o 		= this;
		var nAt 	= parseInt( - o._getCurrentOffset() / o.w );
		n			= Math.max( 0, Math.min( n, o.getNHiddenItems() ) );
		o.scroll( n - nAt );
		
	}

	o.getNVisibleItems = function() {
		return parseInt( Math.floor( this._getVisibleWidth() / this.w ) );
	}
	
	o.getNHiddenItems = function() {
		return ( this.n - this.getNVisibleItems() );	
	}

	o._getNItems = function() {
		var all		= o.get( o.gi ).parentNode.childNodes;
		var n 		= 0;
		for( var i in all ) {
			n 		+= ( all[i].tagName ? 1 : 0 );
		}
		return n;
	}

	o.getCurrentProgress = function() {
		var o 		= this;
		var nAt 	= parseInt( - o._getCurrentOffset() / o.w );
		return ( nAt / o.getNHiddenItems() );
	}

	o.get = function( id ) {
		return this.doc.getElementById( id );
	}
	
	o._checkArrows = function( dx, xEnd, overflow ) {
		var o 		= this;
		var al		= o.get( o.gla );
		var ar		= o.get( o.gra );

		if( dx >= 0 ) { 
			if( dx > 0 ) {
				o.arrOn( ar );
			}
			if( 0 == xEnd || xEnd + dx > 0 ) {
				o.arrOff( al );
			} else {
				o.arrOn( al );
			}
		}
		if( dx <= 0 ) {
			if( dx < 0 ) {
				o.arrOn( al );
			}
			if( - xEnd - dx >= overflow ) {
				o.arrOff( ar );
			} else {
				o.arrOn( ar );
			}	
		}	
	}
	
	o._getElemProp = function( id, prop ) {
		var el		= ( 'string' == typeof( id ) ? this.get( id ) : id );
		var x	 	= ( el ? el[prop] : null );
		return ( x ? parseInt( x ) : 0 );	// not to get NaN		
	}
	
	o._getItemWidth = function() {	
		return this._getElemProp( this.gi, 'scrollWidth' );
	}
	
	o._getItemHeight = function() {
		return this._getElemProp( this.gi, 'scrollHeight' );
	}

	o._getCurrentOffset = function() {
		return this._getElemProp( this.gis, 'offsetLeft' );
	}

	o._getVisibleWidth = function() {
		var o 		= this;
		var el 		= o.get( o.gis ).parentNode;
		return ( o._getElemProp( el, 'offsetWidth' ) );
	}

	o._getOverflow = function() {
		var o 		= this;
		var x1 		= o._getElemProp( o.gis, 'offsetWidth' );
		var x2 		= o._getElemProp( o.get( o.gis ).parentNode, 'offsetWidth' );	
		return x1 - x2;
	}
	
}

