Ext.ns('Nexts.grid');

Nexts.grid.RowExpander = function(config) {
	if (config && config.iconStyle == 'plus') {
		this.baseCls = 'x-grid3-row-expander';
		this.expandedCls = 'x-grid3-row-expanded';
		this.collapsedCls = 'x-grid3-row-collapsed';
	}
	
	Ext.apply(this, config);

	this.addEvents({
		beforeexpand : true,
		expand: true,
		beforecollapse: true,
		collapse: true
	});

	this.state = {};
	
	Nexts.grid.RowExpander.superclass.constructor.call(this);

	this.renderer = this.renderer.createDelegate(this);
};

Ext.extend(Nexts.grid.RowExpander, Ext.util.Observable, {
	id: 'expander',

	dataIndex: '',
	
	header: "",
	
	sortable: false,
	
	fixed: true,
	
	menuDisabled: true,
	
	hideable: false,
	
	rowspan: 2,
	
	width: 20,
	
	baseCls: 'ne-grid-row-expander',
	
	expandedCls: 'ne-grid-row-expanded',
	
	collapsedCls: 'ne-grid-row-collapsed',
	
	/**
	 * @cfg {String} iconStyle 'arrow', 'plus'
	 */
	iconStyle: 'arrow',

	/**
	 * @cfg {String} tpl - record view template
	 */

	/**
	 * @cfg {Object} fieldLabels Object 
	fields: {
		user: { label: 'User name', hidden: true }
	},
	 */

	renderer: function(v, p, record) {
		if (this.rowspan) {
			p.cellAttr = 'rowspan="' + this.rowspan + '"';
		}
		return '<div class="' + this.baseCls + '"></div>';
	},

	init: function(grid) {
		this.grid = grid;

		var view = grid.getView();

		this.saveGetRowClass = view.getRowClass;
		
		view.getRowClass = this.getRowClass.createDelegate(this);

		view.enableRowBody = true;

		view.on({
			rowremoved: this.onRowRemoved,
			refresh: this.clearViews,
			scope: this
		});
		
		grid.on({
			render: this.onRender,
			destroy: this.clearViews,
			scope: this
		});
	},

	onRowRemoved: function(view, index, record) {
		delete this.state[record.id];
	},
	
	clearViews: function() {
		this.state = {};
	},
	
	getRowClass: function(record, rowIndex, p, ds) {
		var cls = '';
		
		if (typeof this.saveGetRowClass == 'function') {
			cls = this.saveGetRowClass.apply(this.grid.view, arguments);
		}
		p.cols = p.cols - 1;

		return cls + '' + (this.state[record.id] ? this.expandedCls : this.collapsedCls);
	},

	onRender: function() {
		this.initFields();

		if (this.tpl) {
			if (typeof this.tpl == 'string') {
				this.tpl = new Ext.Template(this.tpl);
			}
			this.tpl.compile();
		}
		else {
			this.autoCreateTemplate();
		}

		this.grid.getGridEl().on({
			click: this.onClick,
			dblclick: this.onDblClick, 
			keydown: this.onKeyDown,
			scope: this
		});
	},
	
	onClick: function(e, t) {
		if (t.className == this.baseCls
			|| t.className.indexOf('x-grid3-td-expander') >= 0
			|| t.className.indexOf('x-grid3-col-expander') >= 0) {
			e.stopEvent();
			var row = e.getTarget('.x-grid3-row');
			this.toggleRow(row);
		}
	},

	onDblClick: function(e, t) {
		if (t.className == this.baseCls
			|| t.className.indexOf('x-grid3-td-expander') >= 0
			|| t.className.indexOf('x-grid3-col-expander') >= 0) {
		}
		else {
			if (e.getTarget('.x-grid3-row-body-tr')) {
				return;
			}
			
			var row = e.getTarget('.x-grid3-row');
			if (row) {
				e.stopEvent();
				this.toggleRow(row);
			}
		}
	},

	onKeyDown: function(e, t) {
		if (t.tagName == 'INPUT' || t.tagName == 'TEXTAREA') {
		}
		else {
			if (e.getKey() == e.LEFT || e.getKey() == e.RIGHT) {
				var sm = this.grid. getSelectionModel();
				if (sm.getSelections) {
					sm.getSelections().each(function(r) {
						this[e.getKey() == e.RIGHT ? 'expandRow' : 'collapseRow'](this.grid.store.indexOfId(r.id));
					}, this);
				}
			}
		}
	},
	
	renderRowBody: function(record, body, rowIndex) {
		var v = this.getRenderedData(record);
		this.tpl.overwrite(body, v);
	},
	
	clearRowBody: function(record, body, rowIndex) {
		body.innerHTML = '';
	},
	
	toggleRow: function(row) {
		if (typeof row == 'number') {
			row = this.grid.view.getRow(row);
		}
		this[row.className.indexOf(this.collapsedCls) >= 0 ? 'expandRow' : 'collapseRow'](row);
	},

	expandRow: function(row) {
		if (typeof row == 'number') {
			row = this.grid.view.getRow(row);
		}
		if (row.className.indexOf(this.expandedCls) < 0) {
			var record = this.grid.store.getAt(row.rowIndex);
			var body = Ext.DomQuery.selectNode('tr:nth(2) div.x-grid3-row-body', row);
			if (this.fireEvent('beforeexpand', this, record, body, row.rowIndex) !== false) {
				this.state[record.id] = true;
				Ext.fly(row).replaceClass(this.collapsedCls, this.expandedCls);
				this.renderRowBody(record, body, row.rowIndex);
				this.fireEvent('expand', this, record, body, row.rowIndex);
			}
		}
	},

	collapseRow: function(row) {
		if (typeof row == 'number') {
			row = this.grid.view.getRow(row);
		}
		if (row.className.indexOf(this.collapsedCls) < 0) {
			var record = this.grid.store.getAt(row.rowIndex);
			var body = Ext.DomQuery.selectNode('tr:nth(2) div.x-grid3-row-body', row);
			if (this.fireEvent('beforcollapse', this, record, body, row.rowIndex) !== false) {
				delete this.state[record.id];
				Ext.fly(row).replaceClass(this.expandedCls, this.collapsedCls);
				this.fireEvent('collapse', this, record, body, row.rowIndex);
				this.clearRowBody(record, body, row.rowIndex);
			}
		}
	},

	initFields: function() {
		this.fields = this.fields || {};

		var fields = this.grid.store.fields;
		
		fields.each(function(f, i) {
			var o = this.fields[f.name] || {};
			if (o.hidden) {
				return;
			}
			
			var c = this.findColumnConfig(f.name);
			
			if (o.label === undefined) {
				o.label = c ? c.header : f.name;
			}
			
			if (o.renderer === undefined) {
				o.renderer = c ? c.renderer : undefined;
			}
			this.fields[f.name] = o;
		}, this);
	},

	/**
	 * Finds if a configuration exists for a given dataIndex in column model
	 * @private
	 * @param {String} di dataIndex 
	 */
	findColumnConfig: function(di) {
		var config = null;

		Ext.each(this.grid.getColumnModel().config, function(c, i) {
			if (di === c.dataIndex) {
				config = c;
				return false;
			}
		});

		return config;
	},

	autoCreateTemplate: function() {
		this.tpl = '<div class="ne-grid-rowexpander-view"><table border="0" cellspacing="0" cellpadding="0">';

		for (var i in this.fields) {
			var f = this.fields[i];
			if (!f.hidden) {
				this.tpl += '<tr><th nowrap>' + (f.label ? f.label : i) + ':</th><td>{' + i + '}</td></tr>';
			}
		}
		
		this.tpl += '</table></div>';
		
		this.tpl = new Ext.XTemplate(this.tpl);
		this.tpl.compile();
	},
	
	getRenderedData: function(record) {
		var d = record.data;
		var o = {};
		var p = { expander: true };
		for (var i in d) {
			var f = this.fields[i];
			if (f && f.renderer) {
				o[i] = f.renderer(d[i], p, record);
			}
			else {
				if (d[i] === undefined) {
					o[i] = '';
				}
				else {
					o[i] = d[i];
				}
			}
		}
		return o;
	}
});

