/*	Manager JavaScript framework, version 1.1 beta
 *	(c) 2007 Clement Hallet, from AF83 company
 *
/*--------------------------------------------------------------------------*/

Manager.List = Manager.Base.extend({
	
	changeTimer: null,
	completeTimer: null,
	lastPosition: 0,
	oldFirstCellRef: 0,
	cellWidth: 50,	
	options: {
		loader: new Element('span').setHTML("wait")
	},
	
	initialize: function(slider, overflown_area, container, cells, updaterURI, cellTotalCount, options) {
		
		this.parent(container,updaterURI,options);
		
		this.setSlider(slider);
		this.cells = cells;
		this.cellWidth = this.cells[0].clientWidth;
		this.overflown_area = $(overflown_area);
		this.cellTotalCount = cellTotalCount;
	    this.scroll_by_page_only = false; // enable page scrolling only
	
		this.setList();
		
	},

	
		/** Set the slider bar.
		 * 
		 * @param {Slider} slider a Slider control.
		 */
	setSlider: function(slider) {
		if ($defined(slider) ) {
			this.slider = slider;
			this.slider.addEvent('onComplete', function(position){
				if (this.completeTimerOut) {
					this.completeTimerOut = false;
					this.update.delay(200, this);
				}
			}.bind(this));
			this.slider.addEvent('onChange', function(position){
				this.position = position;
				if (this.changeTimerOut) {
					this.changeTimerOut = false;
					this.render.delay(60, this);
				}
			}.bind(this));
		}
	},
	
	/** Set the virtual list, linked to the slider.
	 * 
	 * @param {Slider} slider a Slider control.
	 */
	setList: function() {
		this.totalWidth = this.cellTotalCount * this.cellWidth - this.overflown_area.clientWidth;
		this.completeTimerOut = true;
		this.changeTimerOut = true;
		this.page = 1;
		for(var i = 0; i < this.cells.length; i++){
			 new Manager.Area(this.cells[i],this.updaterURI,{
			     onUpdate:function(transport) {
			         if($defined(transport.getHeader("X-Manager-List-Total-Count")) && transport.getHeader("X-Manager-List-Total-Count") != "")  {
			             this.cellTotalCount = parseInt(transport.getHeader("X-Manager-List-Total-Count"))
			             this.totalWidth = this.cellTotalCount * this.cellWidth - this.overflown_area.clientWidth;
			             if (this.pagetotal) this.pagetotal.setText(this.convList2Page(this.totalWidth) );   
			         }
			          
			     }.bind(this)
			 });
			 this.cells[i].manager.setParameter('offset',i);
		}
	},
	
		/** Go n page up in the list page
		 * 
		 * @param integer n page increment relative to the actual one.
		 */ 
	setPage: function(n){
	 this.slider.set( this.convList2Slide( this.convPage2List( this.page+n) )	);
	 //this.fx_page.periodical(80, this, this.convList2Slide( this.convPage2List( this.page+n) ) );
	},
	
	/*
	fx_page: function(destination){
		//console.log("fx_page("+destination+"); this.position = "+this.position+" ecart= "+ Math.abs( this.position - destination));
		if (10 >= Math.abs( this.position - destination)){
			$clear(this.fx_page.periodical);
			this.slider.set( destination );
		}
		if (this.position>destination) this.slider.set(this.position-10);
		if (this.position<destination) this.slider.set(this.position+10);
	},
		*/
	
	/** Bind the Elements for page. 
	 * 
	 * @param {Element} pagecounter Where to print the page state.
	 * @param {Element} pagetotal Where to print the page total.
	 * @param {Element} prev The previous button.
	 * @param {Element} next The next button.
	 */
	setPageCounter: function(pagecounter, pagetotal, prev, next){
		this.pagecounter = pagecounter;
		this.pagetotal = pagetotal;
		this.elPrevpage=prev;
		this.elNextpage=next;
	
		// info refresh
		if (this.pagecounter != null) {
		  this.pagecounter.setText(this.page);
		};

		if (this.pagetotal != null) {
		  this.pagetotal.setText(this.convList2Page(this.totalWidth) );
		}	

        if (this.elNextpage != null)
        {
            // bind 'next' element on setpage function
            this.elNextpage.addEvent('click', function(e){
            	new Event(e).preventDefault();
            	this.setPage(1);
            }.bind(this));
        }

        if (this.elPrevpage != null)
        {
            // bind 'next' element on setpage function
            this.elPrevpage.addEvent('click', function(e){
            	new Event(e).preventDefault();
            	this.setPage(-1);
            }.bind(this));
        }
	},
	
	render: function() {

		// todo : some calculs may be done only once ?

		this.changeTimerOut = true;
		if(this.totalWidth <= 0) return;

        if (this.position == undefined)
        {
            this.position = 0;
        }
	
		// slider pos
		position = this.position;
	
		// list pos
		var abs_scroll_position = Math.round( this.convSlide2List(position) );
	
		// update page info.
		this.page = this.convList2Page(abs_scroll_position );

        // Logging in location hash if history_log_postion present position
        if (this.slider_history != undefined)
        {
            this.updateHistoryLog(this.slider_history);
        }

		if (this.pagecounter) this.pagecounter.setText(this.page);
		if (this.pagetotal) this.pagetotal.setText(this.convList2Page(this.totalWidth) );
		
		// get the first cell in the list and the value of the real scroll to set
		if (position != this.lastPosition) {
			var firstCellOffset = Math.floor(abs_scroll_position / this.cellWidth);
			var scroll_position = (abs_scroll_position % this.cellWidth);
		} else {
			// no move (!)
			return;
		}
		
		// for each cell: set offfset parameter, then display content if in cache, or the loader if not
		for (var i = firstCellOffset; i < firstCellOffset + this.cells.length; i++) {
			var ref = (i + this.cells.length)  % this.cells.length;
			if (i >= 0 && i < this.cellTotalCount) {
				this.cells[ref].manager.setParameter('offset', i);
				if (this.cells[ref].manager.isCacheAvailable()) 
					// display it directly from the cache
					this.cells[ref].manager.update(true);
				else 
					this.cells[ref].empty().adopt(this.options.loader.clone());
			} else {
				this.cells[ref].manager.removeParameter('offset');
				this.cells[ref].empty();
			}
		}
		
		// cells reorganization
		var shift = (firstCellOffset + this.cells.length) % this.cells.length - this.oldFirstCellRef;
		shift = shift + (shift < 0 ? this.cells.length : 0);

		if(shift != 0) {
			if(shift > this.cells.length / 2) {
				// shift (this.cells.length - shift) cells from right to left
				for(var i = shift; i < this.cells.length; i++) {
					var shiftingRef = (this.oldFirstCellRef + i + this.cells.length ) % this.cells.length;
					this.cells[shiftingRef].injectBefore(this.cells[this.oldFirstCellRef]);
				}
			} else {
				// shift (shift) cells from left to right
				for(var i = shift - 1; i >= 0; i--) {
					var shiftingRef = (this.oldFirstCellRef + i + this.cells.length) % this.cells.length;
					this.cells[shiftingRef].injectAfter(this.cells[(this.oldFirstCellRef + this.cells.length - 1) % this.cells.length]);
				}
			}
		}
        // enable scolling by page
        if (!this.scroll_by_page_only)
        {
		// apply the scroll on container instead of each elements
		    this.container.setStyle("left",-scroll_position + 'px');
	    }
		// save the position in order to make next processing
		this.lastPosition = position;
		this.oldFirstCellRef = (firstCellOffset + this.cells.length) % this.cells.length;


		
	},

 	/** Log current page in window location hash for history management
	 * 
	 * @param {Object} current position log in an  object hash with history['selected'] = current tab selected id.
	 * @return {void}.
	 */
    updateHistoryLog: function (history)
    {
            if (history['selected'] != undefined)
            {
                var location_hash_array = [];
                history[history['selected']] = ( this.position != undefined) ? this.page : 1; // this.page;
                var toto = this.position; 
                for (var out_item in history)
                {
                    location_hash_array.push( out_item + '=' + history[out_item] );
                }
                this.history_log_position = location_hash_array.join("&");
                // changing current page in location hash
                
                window.location.hash = '/'+ this.history_log_position;
            }
    },

	/** Log current page in window location hash for history management
	 * 
	 * @param {string} current position log in query string style.
	 * @return {void}.
	 */

    deprecated_updateHistoryLog: function (history_hash) {
        // var history_hash = this.history_history_hash;
        var tmp_datas = {};
        var hash_datas = history_hash.indexOf("&") > -1 ? history_hash.split('&'): null;
        if (hash_datas != null)
        {
            for (var item_idx = 0 ; item_idx < hash_datas.length ; item_idx++)
            {
                var hist_item = hash_datas[item_idx].indexOf("=") > -1 ? hash_datas[item_idx].split('='): null;
                if (hist_item != null)
                {
                    tmp_datas[hist_item[0]] = hist_item[1];
                }
            }
            if (tmp_datas['selected'] != undefined)
            {
                var location_hash_array = [];
                tmp_datas[tmp_datas['selected']] = ( this.position != undefined) ? this.page : 1; // this.page;
                var toto = this.position; 
                for (var out_item in tmp_datas)
                {
                    location_hash_array.push( out_item + '=' + tmp_datas[out_item] );
                }
                this.history_log_position = location_hash_array.join("&");
                // changing current page in location hash
                
                window.location.hash = '/'+ this.history_log_position;
            }
        }
    },
	
	/** Comput the List position from a Slide positon.
	 * 
	 * @param {integer} pos the slide coord to translate.
	 * @return {integer} computed List position.
	 */
	convSlide2List: function (pos) {
		return (this.totalWidth + this.cellWidth) * pos / this.slider.options.steps;
	},
	
		/** Comput the Slide position from a List position .
	 * 
	 * @param {integer} pos the list coord to translate.
	 * @return {integer} computed List position.
	 */
	convList2Slide: function (pos) {
		return this.slider.options.steps * pos / (this.totalWidth + this.cellWidth) ;
	},
	
	/** Comput the List position from a page number.
	 * 
	 * @param {integer} pos the page num to translate.
	 * @return {integer} computed List pos.
	 */
	convPage2List: function(pos) {

	//	 alert( (pos-1) * this.overflown_area.clientWidth);
		 return (pos-1) * this.overflown_area.clientWidth;
			 //return (pos-1) * Math.floor( this.overflown_area.clientWidth / this.cellWidth) * this.cellWidth;
	},

	/** Comput the page number from a List position.
	 * 
	 * @param {integer} pos the List pos to translate.
	 * @return {integer} computed page number.
	 */
	convList2Page: function(pos) {
		return Math.max(0,Math.round(pos / this.overflown_area.clientWidth)) + 1;
		//return Math.ceil((pos)/ ( Math.floor( this.overflown_area.clientWidth / this.cellWidth)*this.cellWidth) +1);
	},
	
	update: function() {
		this.completeTimerOut = true;
		for(var i= 0; i < this.cells.length; i++) {
			this.cells[i].manager.update(true);
		}
	},
	
	setParameter: function(key,value) {
		for(var i= 0; i < this.cells.length; i++) {
			this.cells[i].manager.setParameter(key,value);
		}
		this.parent(key,value);
	},
	
	removeParameter: function(key) {
		for(var i= 0; i < this.cells.length; i++) {
			this.cells[i].manager.removeParameter(key);
		}
		this.parent(key);
	}

	
});


Manager.List.Helper = new Class({
	initialize: function(helperid, url) {
		this.helperid=helperid;
		this.url=url;
		if ($('area'+helperid) && $('knob'+helperid) ){
						this.slide = new Slider($('area'+helperid), $('knob'+helperid), {steps:$('area'+helperid).clientWidth});
		if ($('container'+helperid) && $('list'+helperid) )
			this.list = new Manager.List(this.slide, $('list'+helperid), $('container'+helperid), $$('div#container'+helperid+' div'),this.url);
		}
		if ($('page_counter'+helperid), $('page_total'+helperid), $('page_prev'+helperid), $('page_next'+helperid)){
			this.list.setPageCounter($('page_counter'+helperid), $('page_total'+helperid), $('page_prev'+helperid), $('page_next'+helperid));
		}		
	}
});
