if (!window.ExtendedDataTable) window.ExtendedDataTable = {};

ExtendedDataTable.DataTable = Class.create({
	initialize : function(id, options) {
		this.id = id;
		$(this.id).component = this; 
		this["rich:destructor"] = "destroy";
		this.groups = [];
		
		// register event handlers
		this.options = options;
		this.selectionManager = new ExtendedDataTable.SelectionManager(options, this);
		
		if (this.options.sortFunction) {
			this.sortFct = this.options.sortFunction;
			this.eventCellClicked = this.OnCellMouseClicked.bindAsEventListener(this);
		}
		this.onGroupToggleFct = this.options.onGroupToggleFunction;
		if (this.options.onColumnResize != null){
			this.onColumnResize = this.options.onColumnResize;
			this.columnWidths = "";
		}		
		this.eventContainerResize = this.OnWindowResize.bindAsEventListener(this);
		this.eventGroupRowClicked = this.OnGroupRowMouseClicked.bindAsEventListener(this);
		Event.observe(window, "resize", this.eventContainerResize);
		this.minColumnWidth = this.options.minColumnWidth;
		
		var grid = this;

		Utils.execOnLoad(
			function(){
				grid.update(true);
			},
			Utils.Condition.ElementPresent(id+':od'), 5);
	},
	
	destroy: function() {
        //var rows = this.tableB.rows;
        //rowCount = rows.length;
        //for(var i = 0; i < rowCount; i++) {
        //    Utils.DOM.Event.removeListeners(rows[i]);
        //}
        
        //remove listeners
        this.selectionManager.removeListeners();
        this.header.removeListeners();
        
        var l = this.groupRows.length;
		for(var i = 0; i < l; i++) {		
			Utils.DOM.Event.removeListeners(this.groupRows[i]);
		}
		
		var headerChildren = this.header.getColumnCells();
		l = headerChildren.length;
		for (var i=0; i<l-1; i++) {
			Utils.DOM.Event.removeListeners(headerChildren[i]);
		};
        
        //null all references to DOM elements
        delete this.selectionManager;
        delete this.header;
        delete this.footer;
        
        $(this.id).component = null;
        this.table = null;
        this.splashScreen = null;
		this.mainDiv = null;
		this.outerDiv = null;
		this.tableB = null;
		this.fakeIeRow = null;
		this.fakeIeBodyRow = null;
		this.cols = null;
		this.scrollingDiv = null;
		this.groupRows = null;
		this.groups = null;
		Event.stopObserving(window, 'resize', this.eventContainerResize);
	},
	
    /**
     * Changes the scroll position of the table to show row of specified index
     */
    showRow: function(rowIndex) {
        var row = $(this.id+":n:"+rowIndex);
        var offsetTop = this.tableB.offsetTop + row.offsetTop;
        var scrollTop = this.scrollingDiv.getElement().scrollTop;
        
        var dS = offsetTop - scrollTop;
        
        if (dS < 0) {
            this.scrollingDiv.getElement().scrollTop = scrollTop + dS;
        }else{
            var scrollDivHeight = this.scrollingDiv.getHeight();
            var rowHeight = row.getHeight();
            dS = dS + rowHeight - scrollDivHeight;
            if (dS > 0) {
                this.scrollingDiv.getElement().scrollTop = scrollTop + dS;
            }
        }        
	},
	
    setColumnWidth: function(columnIndex, newWidth) {
        if (columnIndex >= this.getColumnsNumber) {
            return false;
        }else{
            this.getColumns()[columnIndex].width = newWidth;
        }
    },
    	
	_findParentElement: function(event, element) {
		var el = null;
		if(ClientUILib.isSafari) {
			var targetCell = event.currentTarget;
			if(targetCell && targetCell.tagName.toLowerCase() == element) {
				el = targetCell;
			} else {
				var e = (event.target || event.srcElement);
				while((e != null) && (e.tagName.toLowerCase() != element) && (e != document)){
					e = e.parentNode;
				}//while
				if ((e) && (e.tagName.toLowerCase() == element)){
					el = e;
				}
			}
		} else {
			el = Event.findElement(event, element);
		}
		return el;
	},
	
	OnCellMouseClicked: function(event) {
		//get column id
		var el = this._findParentElement(event, "th");
		var columnId = (el) ? el.id : null;
			
		if (columnId && (columnId != "")){
			this.showSplashScreen();
			this.sortFct(event, columnId);		
		}
		Event.stop(event);	
	},
	
	preSendAjaxRequest: function(){
		//remove listeners
		Event.stopObserving(window, 'resize', this.eventContainerResize);
		//Event.stopObserving(document, 'mousemove', this.header.eventSepMouseMove);
		//Event.stopObserving(document, 'mouseup', this.header.eventSepMouseUp);
		//show splash screen
		this.showSplashScreen();
	},
		
	showSplashScreen: function(){
        if (ClientUILib.isOpera) {
            this.mainDiv.setStyle({display:'none'});
        }
        this.table.setStyle({visibility:'hidden'});
        var splshscr = this.splashScreen;
        splshscr.className = 'extdt-ss-vsbl';
	},
	
	hideSplashScreen: function(){
        if (ClientUILib.isOpera) {
            this.mainDiv.setStyle({display:''});
        }
		this.table.setStyle({visibility:'visible'});
		this.splashScreen.className = 'extdt-ss-hdn';		
	},	
	
	OnWindowResize: function(event) {
		this.updateLayout();
	},
	getColumnsNumber: function() {
		return this.columnsNumber;
	},
	getColWidth: function(columnNumber) {
		
	},
	getColumns: function() {
		return this.cols;
	},
	OnGroupRowMouseClicked: function(event) {
		
		var groupRow = this._findParentElement(event, "tr");
		var bExpanded = !(groupRow.getAttribute('expanded') == 'true');
		var sExpanded = bExpanded ? 'true' : 'false';
		var groupIndex = parseInt(groupRow.getAttribute('groupindex'));
		if (this.onGroupToggleFct){
			this.onGroupToggleFct(event, groupIndex);
		}
		groupRow.setAttribute('expanded', sExpanded);
		var imageDiv = groupRow.firstChild.firstChild.firstChild;
		this.toggleImageSource(imageDiv);
		this.setGroupExpanded(groupIndex, bExpanded);
		Event.stop(event);
	},
	
	toggleImageSource: function(imageDiv) {
		var src = imageDiv.getAttribute('src');
		var alternateSrc = imageDiv.getAttribute('alternatesrc');
		imageDiv.setAttribute('src', alternateSrc);
		imageDiv.setAttribute('alternatesrc', src);		
	},
	
    getColumnWidth: function(columnNumber) {
        if ((columnNumber < this.getColumnsNumber()) && (columnNumber >=0)) {
            var col = this.getColumns()[columnNumber];
            if (col.offsetWidth != null) {
                if (ClientUILib.isOpera) {
                    return parseInt(col.width);
                }else{
                    return col.offsetWidth;
                }
            }else{
                return parseInt(col.width);
            }
        }else{
            return null;
        }
    },
	
	setGroupExpanded: function(iGroupIndex, bValue) {
		var group = this.groups[iGroupIndex];
		
		var sVisibility;
		var sBorder;
		var sEmptyCells;
		
		if (bValue) {
			sVisibility = '';
			sBorderStyle = '';
		}else{
			sVisibility = 'none';
			sBorderStyle = 'none';
		}
		var size = group.size();
		for (var i=0; i<size; i++) {
			group[i].style.display = sVisibility;
			if (ClientUILib.isIE){
				//prevent IE from showing borders of cells
				//which parents have been hidden :|
				var cells = group[i].childNodes;
				var l = cells.length;
				for (var j = 0; j < l; j++) {
					cells[j].style.borderStyle = sBorderStyle;
				}
			}
		}
	},
	
	createControls: function() {
		var id = this.id;
		this.table = new ClientUI.common.box.Box(this.id +":tu",null,true);
		var table = this.table;
		this.splashScreen = $(this.id+":splashscreen");
		this.mainDiv = new ClientUI.common.box.Box(this.id,null,true);
		this.outerDiv = new ClientUI.common.box.Box(this.id +":od",null,true);
		this.tableB = $(this.id +":n")
		this.fakeIeRow = $(this.id +":fakeIeRow");
		this.fakeIeBodyRow = $(this.id +":body:fakeIeRow");
		this.header = new ExtendedDataTable.DataTable.header(this.id +":header",this);
		this.header.minColumnWidth = this.minColumnWidth;
		var colgroup = $(this.id +":colgroup:body");
		this.cols = colgroup.getElementsByTagName("col");
		this.columnsNumber = this.cols.length;
		this.scrollingDiv = new ClientUI.common.box.Box(this.id +":sd",null,true);
		this.groupRows = [];
		var tfoot = table.getElement().getElementsByTagName('tfoot');
        this.footer = $(this.id +":footer");
		if (ClientUILib.isOpera) {
			//no overflow-x nor overflow-y in Opera
			this.scrollingDiv.setStyle({overflow: 'scroll',
				width: this.mainDiv.getWidth()
			});
			this.table.setStyle({width: this.mainDiv.getWidth()});
		};
		
		var i = 0;
		var groupRow = $(id+':group-row:'+i);
		while (groupRow != null) {
			this.groupRows[i] = groupRow;
			Utils.DOM.Event.removeListeners(groupRow);
			Utils.DOM.Event.observe(groupRow,'click',this.eventGroupRowClicked);
			i++;
			groupRow = $(id+':group-row:'+i);
		}
	},
	getScrollbarWidth: function() {
		var sd = this.scrollingDiv.getElement();
		return sd.offsetWidth - sd.clientWidth;
	},
	validateColumnsWidth: function(columns,excessWidth) {  	   
		var i=1;
		var endIndex = columns.length-1;
		while ((i < endIndex) && (excessWidth > 0)) {
            if (ClientUILib.isIE) {
                var colWidth = parseInt(this.getColumns()[i].width) - 1;
            }else{
                var colWidth = this.getColumnWidth(i);
            }
            var spareWidth = colWidth - this.minColumnWidth;
            var dW;
            if (spareWidth >= excessWidth) {
                dW = excessWidth; 
            }else{
                dW = spareWidth;
            }
            this.setColumnWidth(i, colWidth - dW);
            this.header.setColumnWidth(i, colWidth - dW);
            excessWidth -= dW;
            i++;
		/*
			var col = columns[columns.length-i-1];
			var spareWidth = col.offsetWidth - this.minColumnWidth;
			if (spareWidth > excessWidth) {
				col.width = col.offsetWidth - excessWidth;
				columns[endIndex - i].width = col.width;
				excessWidth = 0;
			}else{
				col.width = col.offsetWidth - spareWidth;
				columns[endIndex - i].width = col.width;
				excessWidth -= spareWidth;
			}
		*/
		}
	},
	
	getFooterHeight: function() {
        if (this.footer) {
            return this.footer.getHeight();
        }else{
            return 0;
        }
	},
	
	updateLayout: function() {
	    ClientUILib.log(ClientUILogger.INFO, "updateLayout");
		var table = this.table.getElement();
		var outerDiv = this.outerDiv.getElement();
		var cols = this.getColumns();
		var header = this.header;
		var scrollingDiv = this.scrollingDiv;
		var mainDivHeight = this.mainDiv.getHeight();
		var mainDivWidth = this.mainDiv.getWidth();
		var headerChildren = header.getColumnCells();
		
		var footers = table.getElementsByTagName('tfoot');
		var footerHeight = this.getFooterHeight();

		var columnsNumber = this.getColumnsNumber();		

		var visibleHeaderWidth = this.header.getVisibleWidth();
        var scrollbarWidth = scrollingDiv.getElement().offsetWidth - scrollingDiv.getElement().clientWidth;
        var maxAllowedWidth = this.mainDiv.getWidth() - scrollbarWidth;
        var excessWidth = this.header.getVisibleWidth() - maxAllowedWidth - 1;
		if (excessWidth > 0) {
			this.validateColumnsWidth(cols,excessWidth);
		};
		if (ClientUILib.isOpera) {
            var _stl = 2;
            var cols = this.header.getColumns();
            var columnsNumber = this.header.getColumnsNumber();
            for (var i=0; i<columnsNumber-1; i++) {
                ClientUILib.log(ClientUILogger.INFO, "this.getColumnWidth(i) "+this.getColumnWidth(i));
                cols[i].width = this.getColumnWidth(i) - _stl;
            }
		};
        cols[columnsNumber-1].width = null;
        cols[cols.length-1].width = null;
		var newHeight = mainDivHeight - header.getHeight() - footerHeight - 2;
		newHeight -= this.header.getCaptionHeight();
		scrollingDiv.setStyle('height:'+ newHeight +'px;');
		var l = headerChildren.length;
		for (var i=0; i < l-1; i++) {
			var headerChild = headerChildren[i];
			Utils.DOM.Event.removeListeners(headerChild);
            Utils.DOM.Event.observe(headerChild,'mouseover',this.header.eventHeaderCellMouseOver);
            Utils.DOM.Event.observe(headerChild,'mouseout',this.header.eventHeaderCellMouseOut);
			var isSortable = headerChild.getAttribute('sortable');
			if ((isSortable) && (isSortable.indexOf('true') == 0)) {
				Utils.DOM.Event.observe(headerChild, 'click',  this.eventCellClicked);
			}
		};
		header.adjustSeparators();
		this.hideSplashScreen();
	},
    update: function(refreshEvents) {
        this.createControls();
        if ( !ClientUILib.isIE ) {
            if (this.fakeIeRow) {
				this.table.getElement().deleteRow(this.fakeIeRow);	
				this.fakeIeRow = null;
			}
			if (this.fakeIeBodyRow) {
				this.tableB.deleteRow(this.fakeIeBodyRow);
				this.fakeIeBodyRow = null;
			}
		}		
		this.selectionManager.refreshEvents();
		this.updateLayout();
		this.selectionManager.restoreState();
	}

});