/*
 * Ext Scheduler v1.5 beta
 * Copyright(c) 2009-2010 Mats Bryntse Consulting
 * mats@ext-scheduler.com
 * http://www.ext-scheduler.com/license.html
 *
 * Based on ColumnLock v1.7.1 for Ext 3
 */
 
Ext.ns('Sch');

// Added after Ext 3.0.0
Ext.applyIf(Ext.grid.GridView.prototype, {
	getScrollOffset: function(){
		return Ext.isDefined(this.scrollOffset) ? this.scrollOffset : Ext.getScrollBarWidth();
	}
});

/**
 * @class Sch.LockingSchedulerView
 * @extends Sch.SchedulerView
 * This class provides column locking support
 * @constructor
 * @param {Object} config The object containing the configuration of this model.
 */
Sch.LockingSchedulerView = Ext.extend(Sch.SchedulerView, {
	lockText : Ext.ux.grid.LockingGridView.prototype.lockText,
	unlockText : Ext.ux.grid.LockingGridView.prototype.unlockText,
	rowBorderWidth : Ext.ux.grid.LockingGridView.prototype.rowBorderWidth,
	lockedBorderWidth : Ext.ux.grid.LockingGridView.prototype.lockedBorderWidth,
	initTemplates : function(){
		var ts = this.templates || {};
		if(!ts.master){
			ts.master = new Ext.Template(
				'<div class="x-grid3" hidefocus="true">',
					'<div class="x-grid3-locked">',
						'<div class="x-grid3-header"><div class="x-grid3-header-inner"><div class="x-grid3-header-offset" style="{lstyle}">{lockedHeader}</div></div><div class="x-clear"></div></div>',
						'<div class="x-grid3-scroller"><div class="x-grid3-body" style="{lstyle}">{lockedBody}</div><div class="x-grid3-scroll-spacer"></div></div>',
					'</div>',
					'<div class="x-grid3-viewport x-grid3-unlocked">',
						'<div class="x-grid3-header"><div class="x-grid3-header-inner"><div class="x-grid3-header-offset" style="{ostyle}">{header}</div></div><div class="x-clear"></div></div>',
						'<div class="x-grid3-scroller"><div class="x-grid3-body" style="{bstyle}">{body}</div><a href="#" class="x-grid3-focus" tabIndex="-1"></a></div>',
					'</div>',
					'<div class="x-grid3-resize-marker">&#160;</div>',
					'<div class="x-grid3-resize-proxy">&#160;</div>',
				'</div>'
			);
		}
		this.templates = ts;
		Sch.LockingSchedulerView.superclass.initTemplates.call(this);
	},
	getEditorParent : Ext.ux.grid.LockingGridView.prototype.getEditorParent,
	initElements : Ext.ux.grid.LockingGridView.prototype.initElements,
	getLockedRows : Ext.ux.grid.LockingGridView.prototype.getLockedRows,
	getLockedRow : Ext.ux.grid.LockingGridView.prototype.getLockedRow,
	
	getCell : function(row, col){
		var llen = this.cm.getLockedCount();
		if(col < llen){
			return this.getLockedRow(row).getElementsByTagName('td')[col];
		}
		return Sch.LockingSchedulerView.superclass.getCell.call(this, row, col - llen);
	},
	getHeaderCell : function(index){
		var llen = this.cm.getLockedCount();
		if(index < llen){
			return this.lockedHd.dom.getElementsByTagName('td')[index];
		}
		return Sch.LockingSchedulerView.superclass.getHeaderCell.call(this, index - llen);
	},
	addRowClass : function(row, cls){
		var r = this.getLockedRow(row);
		if(r){
			this.fly(r).addClass(cls);
		}
		Sch.LockingSchedulerView.superclass.addRowClass.call(this, row, cls);
	},
	removeRowClass : function(row, cls){
		var r = this.getLockedRow(row);
		if(r){
			this.fly(r).removeClass(cls);
		}
		Sch.LockingSchedulerView.superclass.removeRowClass.call(this, row, cls);
	},
	removeRow : function(row) {
		Ext.removeNode(this.getLockedRow(row));
		Sch.LockingSchedulerView.superclass.removeRow.call(this, row);
	},
	removeRows : function(firstRow, lastRow){
		var bd = this.lockedBody.dom;
		for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){
			Ext.removeNode(bd.childNodes[firstRow]);
		}
		Sch.LockingSchedulerView.superclass.removeRows.call(this, firstRow, lastRow);
	},
	syncScroll : function(e){
		var mb = this.scroller.dom;
		this.lockedScroller.dom.scrollTop = mb.scrollTop;
		Sch.LockingSchedulerView.superclass.syncScroll.call(this, e);
	},
	updateSortIcon : Ext.ux.grid.LockingGridView.prototype.updateSortIcon,
	updateAllColumnWidths : Ext.ux.grid.LockingGridView.prototype.updateAllColumnWidths,
	updateColumnWidth : Ext.ux.grid.LockingGridView.prototype.updateColumnWidth,
	updateColumnHidden : Ext.ux.grid.LockingGridView.prototype.updateColumnHidden,
	
	doRender : function(cs, rs, ds, startRow, colCount, stripe){
		var ts = this.templates, ct = ts.cell, rt = ts.row, last = colCount-1,
			tstyle = 'width:'+this.getTotalWidth()+';',
			lstyle = 'width:'+this.getLockedWidth()+';',
			buf = [], lbuf = [], cb, lcb, c, p = {}, rp = {}, r, events, g = this.grid;
		for(var j = 0, len = rs.length; j < len; j++){
			r = rs[j]; cb = []; lcb = [];
			var rowIndex = (j+startRow),
			    resId = r.get('Id');
			
			// @Modification: Events for current row
            events = this.es.data.filterBy(function(brec) {
                return brec.data.ResourceId == resId;
            });
            
			for(var i = 0; i < colCount; i++){
				c = cs[i];
				p.id = c.id;
				p.css = (i === 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '')) +
                    (this.cm.config[i].cellCls ? ' ' + this.cm.config[i].cellCls : '');
				p.attr = p.cellAttr = '';
				p.cellCtCls = '';
				// @Modification: Added events and g to param list
                p.value = c.renderer(r.data[c.name], p, r, rowIndex, i, ds, events, g);
				p.style = c.style;
				if(Ext.isEmpty(p.value)){
					p.value = '&#160;';
				}
				if(this.markDirty && r.dirty && Ext.isDefined(r.modified[c.name])){
					p.css += ' x-grid3-dirty-cell';
				}
				if(c.locked){
					lcb[lcb.length] = ct.apply(p);
				}else{
					cb[cb.length] = ct.apply(p);
				}
			}
			var alt = [];
			if(stripe && ((rowIndex+1) % 2 === 0)){
				alt[0] = 'x-grid3-row-alt';
			}
			if(r.dirty){
				alt[1] = ' x-grid3-dirty-row';
			}
			rp.cols = colCount;
			if(this.getRowClass){
				alt[2] = this.getRowClass(r, rowIndex, rp, ds);
			}
			rp.alt = alt.join(' ');
			rp.cells = cb.join('');
			rp.tstyle = tstyle;
			buf[buf.length] = rt.apply(rp);
			rp.cells = lcb.join('');
			rp.tstyle = lstyle;
			lbuf[lbuf.length] = rt.apply(rp);
		}
		return [buf.join(''), lbuf.join('')];
	},
	processRows : Ext.ux.grid.LockingGridView.prototype.processRows,
	afterRender : Ext.ux.grid.LockingGridView.prototype.afterRender,
	renderUI : Ext.ux.grid.LockingGridView.prototype.renderUI,
	
	layout : function(){
		if(!this.grid.getColumnModel().getColumnCount() == this.grid.nbrStaticColumns){
			return;
		}
		Ext.ux.grid.LockingGridView.prototype.layout.call(this);
	},
	getOffsetWidth : Ext.ux.grid.LockingGridView.prototype.getOffsetWidth,
	
	// Overridden to handle multiple rows
	renderHeaders : function() {
	    var cm = this.cm,
			ts = this.templates,
			ct = ts.hcell,
			cb = [], lcb = [],
			p = {},
			len = cm.getColumnCount(),
			last = len - 1,
			twValue = this.cm.getTotalWidth() - this.cm.getTotalLockedWidth(),
			tw = twValue + 'px',
			lw = this.getLockedWidth(),
			lockedHeaders = '',
			unlockedHeaders = '',
			i;
	    
	    // Process standard headers		
		for(i = 0; i < len; i++){
			p.id = cm.getColumnId(i);
			p.value = cm.getColumnHeader(i) || '';
			p.style = this.getColumnStyle(i, true);
			p.tooltip = this.getColumnTooltip(i);
			p.css = (i === 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '')) +
                (cm.config[i].headerCls ? ' ' + cm.config[i].headerCls : '');
			if(cm.config[i].align == 'right'){
				p.istyle = 'padding-right:16px';
			} else {
				delete p.istyle;
			}
			if(cm.isLocked(i)){
				lcb[lcb.length] = ct.apply(p);
			}else{
				cb[cb.length] = ct.apply(p);
			}
		}
		
	    // Process extra row headers		
		var rows = cm.rows, width, id, group, widthString, gcol;
		
		for (var row = 0, rlen = rows.length; row < rlen; row++) {
			var r = rows[row], cells = [];
		    
		    // Start on 1 since first group is always the locked group
			for (i = 1, gcol = 0, len = r.length; i < len; i++) {
				group = r[i];
				group.colspan = group.colspan || 1;
				id = this.getColumnId(group.dataIndex ? cm.findColumnIndex(group.dataIndex) : gcol);
				
				width = twValue * group.width;
				
                widthString = (Ext.isBorderBox || (Ext.isWebKit && !Ext.isSafari2) ? width : (width - this.borderWidth > 0 ? width - this.borderWidth : 0)) + 'px;';
				
				cells[i] = ts.gcell.apply({
					cls: 'sch-timeheader ' + (group.header ? 'ux-grid-hd-group-cell' : 'ux-grid-hd-nogroup-cell'),
					id: id,
					row: row,
					style: 'width:' + widthString + (group.align ? 'text-align:' + group.align + ';' : ''),
					tooltip: group.tooltip ? (Ext.QuickTips.isEnabled() ? 'ext:qtip' : 'title') + '="' + group.tooltip + '"' : '',
					istyle: group.align == 'right' ? 'padding-right:16px' : '',
					btn: this.grid.enableHdMenu && group.header,
					value: (width > 10) ? (group.header || '&nbsp;') : '&nbsp;'
				});
				gcol += group.colspan;
			}
			
			unlockedHeaders += ts.header.apply({
				tstyle: 'width:' + tw,
				cells: cells.join('')
			});
			
			lockedHeaders += ts.header.apply({
			    cells : ts.gcell.apply({
					cls: 'x-grid3-cell-first x-grid3-cell-last ux-grid-hd-nogroup-cell',
					value: '&nbsp;',
					row: row,
			        id : 0,
				    style: 'width:' + lw
			    }),
			    tstyle:'width:'+lw+';'
			});
		}
		
		unlockedHeaders += ts.header.apply({cells: cb.join(''), tstyle:'width:'+tw+';'});
		lockedHeaders += ts.header.apply({cells: lcb.join(''), tstyle:'width:'+this.getLockedWidth()+';'});
		
		return [
		    unlockedHeaders,
			lockedHeaders
		];
	},
	
	// Overridden
	updateHeaders : function(){
		var hd = this.renderHeaders();
		this.innerHd.firstChild.innerHTML = hd[0];
		this.innerHd.firstChild.style.width = this.getOffsetWidth();
		Ext.fly(this.innerHd.firstChild).select('table:first-child').setWidth(this.getTotalWidth());
		this.lockedInnerHd.firstChild.innerHTML = hd[1];
		var lw = this.getLockedWidth();
		this.lockedInnerHd.firstChild.style.width = lw;
		Ext.fly(this.lockedInnerHd.firstChild).select('table').setWidth(lw);
	},
	
	getResolvedXY : Ext.ux.grid.LockingGridView.prototype.getResolvedXY,
	syncFocusEl : function(row, col, hscroll){
		Sch.LockingSchedulerView.superclass.syncFocusEl.call(this, row, col, col < this.cm.getLockedCount() ? false : hscroll);
	},
	ensureVisible : function(row, col, hscroll){
		return Sch.LockingSchedulerView.superclass.ensureVisible.call(this, row, col, col < this.cm.getLockedCount() ? false : hscroll);
	},
	insertRows : Ext.ux.grid.LockingGridView.prototype.insertRows,
	
    getColumnStyle : Ext.ux.grid.LockingGridView.prototype.getColumnStyle,
	getLockedWidth : Ext.ux.grid.LockingGridView.prototype.getLockedWidth,
	getTotalWidth : Ext.ux.grid.LockingGridView.prototype.getTotalWidth,
	
	// Overridden to include start/end dates
	getColumnData : function(){
		var cs = [], cm = this.cm, colCount = cm.getColumnCount();
		for(var i = 0; i < colCount; i++){
			var name = cm.getDataIndex(i);
			cs[i] = {
                name : name || '', 
				renderer : cm.getRenderer(i),
				id : cm.getColumnId(i),
				style : this.getColumnStyle(i),
				locked : cm.isLocked(i),
				
				start : cm.config[i].start,
                end : cm.config[i].end
			};
		}
		return cs;
	},
	renderBody : Ext.ux.grid.LockingGridView.prototype.renderBody,
	refreshRow : Ext.ux.grid.LockingGridView.prototype.refreshRow,
	refresh : Ext.ux.grid.LockingGridView.prototype.refresh,
	onDenyColumnLock : Ext.ux.grid.LockingGridView.prototype.onDenyColumnLock,
	onColumnLock : Ext.ux.grid.LockingGridView.prototype.onColumnLock,
	
	initData : function(ds, cm){
		if(this.cm){
			this.cm.un('columnlockchange', this.onColumnLock, this);
		}
		Sch.LockingSchedulerView.superclass.initData.call(this, ds, cm);
		if(this.cm){
			this.cm.on('columnlockchange', this.onColumnLock, this);
		}
	},
	
	handleHdMenuClick : function(item){
		var index = this.hdCtxIndex,
			cm = this.cm,
			id = item.getItemId(),
			llen = cm.getLockedCount();
		switch(id){
			case 'lock':
				if(cm.getColumnCount(true) <= llen + 1){
					this.onDenyColumnLock();
					return;
				}
				if(llen != index){
					cm.setLocked(index, true, true);
					cm.moveColumn(index, llen);
					this.grid.fireEvent('columnmove', index, llen);
				}else{
					cm.setLocked(index, true);
				}
			break;
			case 'unlock':
				if(llen - 1 != index){
					cm.setLocked(index, false, true);
					cm.moveColumn(index, llen - 1);
					this.grid.fireEvent('columnmove', index, llen - 1);
				}else{
					cm.setLocked(index, false);
				}
			break;
			default:
				return Sch.LockingSchedulerView.superclass.handleHdMenuClick.call(this, item);
		}
		return true;
	},
	handleHdDown : function(e, t){
		Sch.LockingSchedulerView.superclass.handleHdDown.call(this, e, t);
		if(this.grid.enableColLock !== false){
			if(Ext.fly(t).hasClass('x-grid3-hd-btn')){
				var hd = this.findHeaderCell(t),
					index = this.getCellIndex(hd),
					ms = this.hmenu.items, cm = this.cm;
				ms.get('lock').setDisabled(cm.isLocked(index));
				ms.get('unlock').setDisabled(!cm.isLocked(index));
			}
		}
	},
	syncHeaderHeight : Ext.ux.grid.LockingGridView.prototype.syncHeaderHeight,
	updateLockedWidth : Ext.ux.grid.LockingGridView.prototype.updateLockedWidth,
	
	// Ext Scheduler additions/overrides
	// -----------------------
	
	// Overridden to support mouse over effect for grouping header rows
    handleHdOver : function(e, t){
        var hd = this.findHeaderCell(t) || e.getTarget('.ux-grid-hd-group-cell');
        if(hd && !this.headersDisabled){
            var isLockedGroupHeader = !!hd.className.match('.ux-grid-hd-group-cell');
            this.activeHdRef = t;
            this.activeHdIndex = this.getCellIndex(hd);
            var fly = this.fly(hd), 
                menuDisabled = this.cm.isMenuDisabled(this.activeHdIndex);
            this.activeHdRegion = fly.getRegion();
            if(isLockedGroupHeader || hd.className.match('sch-timeheader') || !menuDisabled){
                fly.addClass('x-grid3-hd-over');
            }
            
            if (!menuDisabled) {
                this.activeHdBtn = fly.child('.x-grid3-hd-btn');
                if(this.activeHdBtn){
                    this.activeHdBtn.dom.style.height = (hd.firstChild.offsetHeight-1)+'px';
                }
            }
        }
    },
    
	getAccColumnWidth : function(endCol) {
	    var w = 0,
            cm = this.cm,
            i;
             
        for (i = this.grid.nbrStaticColumns; i < endCol; i++) {
            if (!cm.isHidden(i)) {
                w += cm.getColumnWidth(i);
            }
        }
        
        return w;
	},
	
    fitTimeColumns : function() {
        var cm = this.cm,
            colW = (this.scroller.getWidth() - this.getScrollOffset())/ (cm.getColumnCount() - cm.getLockedCount());
	    this.updateTimeColumnWidths(colW);
    }
});


