ClientUILib.declarePackage("ClientUI.controls.grid.ScrollableGrid");

ClientUI.controls.grid.ScrollableGrid = Class.create(ClientUI.controls.grid.Grid, {
	initialize: function($super, options) {
		this.startInitTime = (new Date()).getTime();
		
		this.options = options;
		this.client_id = this.options.client_id;
		this.rows_count = $(this.client_id + "_rows_input").value;
		this.scroll_si = $(this.client_id + ":si");
		this.columns_count = this.options.columnsCount;
		this.splash_id = this.options.splash_id; 
		this.dataModel = new ClientUI.controls.grid.FakeArrayDataModel(this.rows_count, this.columns_count, this.client_id);
		
		this.templates = [
			{pane: GridLayout_Enum.HEADER,	ref: this.client_id +"_" + "GridHeaderTemplate"},
			{pane: GridLayout_Enum.BODY, 	ref: this.client_id +"_" + "GridBodyTemplate"},
			{pane: GridLayout_Enum.FOOTER,	ref: this.client_id +"_" +  "GridFooterTemplate"}
		];			
		var grid = this;
		var s = $super;
		
		Event.onReady(function(){
			grid.init(s);
		});		
		Utils.execOnLoad(
			function(){
				grid.init(s);
			},
			Utils.Condition.ElementPresent(grid.client_id), 100);
				
		this.endInitTime = (new Date()).getTime();
		this.rowCallbacks = [];
	},

// initialize parent Grid	
	
	init: function(superCtor){
		// mark that grid control initialized
		if(!this.isInitialized) {
			this.isInitialized = true;
			this.startCreateTime = (new Date()).getTime();
			
			superCtor(this.client_id, this.dataModel, this.templates);
						
			this.endCreateTime = (new Date()).getTime();
						
			// suspend some processing
			setTimeout(function() {
				this.startPostProcessTime = (new Date()).getTime();
				
				this.eventOnPostSort = new ClientUI.common.utils.CustomEvent('OnSort');
				this.eventOnPostScroll = new ClientUI.common.utils.CustomEvent('OnScroll');
							
				//var progress = new ClientUI.common.box.SplashBox(this.splash_id, null, 300, true);
				//this.setProgressCtrl(progress);
				Event.observe(this.eventOnSort, "on sort",  this.onSorted.bindAsEventListener(this));
				if (this.options.selectionInput) {
					this.selectionManager = new ClientUI.controls.grid.SelectionManager(this);
				}
				
				this.endPostProcessTime = (new Date()).getTime();
			}.bind(this), 500);
			
			if(this.scroll_si.value !=''){
				var options = this.scroll_si.value.split(',');
				this.restoreScrollState(options[0],options[1],options[2]);  		
			}
			
			var form = this.getForm($(this.client_id));						
			Event.observe(form, "submit",this.restoreScrollPos.bindAsEventListener(this));
		}
	},	
	
	getForm: function(element){
		var node = element;
		if(node){
			while(node.tagName.toUpperCase()  != 'FORM'){
				node = node.parentNode;	
			}
		}
		
		return node;	
	},
	
	onSortComplete : function(request, event, data){
		var options = request.getJSON("options");				
		Utils.AJAX.updateRows(options,request,
								this,this.client_id, 
								[this.updateSelectionCallBack], 
								[function(){
									this.selectionManager.restoreState();
									this.eventOnPostSort.fire(options.column, options.order);
								}]);
		this.updateLayout();
	},
	onScrollComplete : function(request, event, data){
		var options = this.dataModel.getCurrentOptions();
		window.loadingServerTime = (new Date()).getTime();
		Utils.AJAX.updateRows(options,request,
								this,this.client_id, 
								[this.updateSelectionCallBack],
								[function(){
									this.selectionManager.restoreState();
									this.eventOnPostScroll.fire(this.getBody().currRange.start);
								}]);								
								
		window.loadingEndTime = (new Date()).getTime();
		
		// TODO: remove this time statistic logging
		ClientUILib.log(ClientUILogger.ERROR, "Total time of data loading of "+options.count+" rows is: " + (window.loadingEndTime - window.loadingStartTime) + " miliseconds.");
		ClientUILib.log(ClientUILogger.WARNING, "...Server load time: " + (window.loadingServerTime - window.loadingStartTime));
		ClientUILib.log(ClientUILogger.WARNING, "...DOM updated time: " + (window.loadingUpdateTime - window.loadingServerTime));
		ClientUILib.log(ClientUILogger.WARNING, "...Grid invalidation time: " + (window.loadingInvalidateTime - window.loadingUpdateTime));
		ClientUILib.log(ClientUILogger.WARNING, "...Selection mng time: " + (window.loadingEndTime - window.loadingInvalidateTime));
	},
	
	onSorted: function(sortEvent) {
		this.options.onSortAjaxUpdate(sortEvent);
	},
	
	updateSelectionCallBack: function(argMap) {
		if (this.selectionManager) {
			this.selectionManager.addListener(argMap.row, argMap.index);
		}
	},
	
	setSizes: function(width, height) {
		var style = this.element.style;
		style.width = width +"px";
		style.height = height +"px";
		this.updateLayout();
	},
	
	doCollapse: function(index) {
		var header = this.getHeader();
		var flength = header.headerFrozenRow.getElement().rows[0].cells.length;
		var nlength = header.headerRow.getElement().rows[0].cells.length;
		if(index < flength + nlength - 1) {
			var frozen = true;
			if(index >= flength) {
				index -= flength;
				frozen = false;			
			}
			this.hideColumn(index, frozen);
		}
	},
	
	hideColumn: function(index, frozen) {
		this.getHeader().hideColumn(index, frozen);
		this.getBody().hideColumn(index, frozen);
		if(this.getFooter()) {this.getFooter().hideColumn(index, frozen);}				
		this.updateLayout();
	},
	
	restoreScrollState: function(scrollPos, start, end) {
		
		var body = this.getBody(); 
		body.scrollBox.getElement().scrollTop = scrollPos;
		body.currentPos = scrollPos;
		body.currRange.start = start;
		body.currRange.end = end;
		body._onContentVScroll(scrollPos);
		var visibleRowPos = body.currRange.start * body.defaultRowHeight;
		//setTimeout(function(){
			body.templFrozen.moveToY(visibleRowPos);
			body.templNormal.moveToY(visibleRowPos);
		//}, 500);
	},
	
	getScrollPos: function() {
		return this.getBody().currentPos;
	},
	
	restoreScrollPos: function(){
		var body = this.getBody();
		var start = body.currRange.start;
		var end = body.currRange.end;
		var index = this.getScrollPos();
		this.scroll_si.value = index + "," + start + "," + end; 
	}
});

Object.extend(ClientUI.controls.grid.ScrollableGrid.prototype, {
	/**
	* Occured when scroll position adjusted
	*/
	eventOnPostScroll: {},
	
	/**
	 * Occured when sorting adjusted
	 */
	eventOnPostSort: {}
	
});