/**
 *
 *  $Id: pjhtmlbrowse.js,v 1.7 2008/04/17 16:59:36 danielg Exp $
 *  
 *
 * @module Widgets
 * Copyright 2006 Nethrom Software
 */

if( typeof Projapi == "undefined") { var Projapi = {}; }

if( typeof Projapi.Widgets == "undefined") { Projapi.Widgets = {}; }


//
//
// ------------------------------------- PJHTMLBrowse
//  
//
//
//
/**
 * Creates a new PJHTMLBrowse object
 * @constructor
 * @param {String} _objectId The Object Name / Id of this field
 */
Projapi.Widgets.PJHTMLBrowse = function( _objectId, _properties) {
	_objectId = _objectId || Projapi.UI.GenerateId();
	
	Projapi.Widgets.PJHTMLBrowse.superclass.constructor.call(this, _objectId, _properties);
	this._properties = Object.extend({
		contentBefore: '',
		contentBody: '<div id="{oThis._objectName + "_" + {rowid}}" class="browseItem">{rowid}</div>',
		contentSeparator: '',
		contentAfter: '',
		position: 0,
		pageSize: 10,
		createToolbar: true
	}, this._properties);
	
	this._contentDOMNode = null;
	
	this._dataSource = null;
	this._navigationSource = null;
	this.toolbar = null;
}

Projapi.extend(Projapi.Widgets.PJHTMLBrowse, Projapi.Base.iPJVisualObject);

Projapi.Widgets.PJHTMLBrowse.prototype.NavigationSourceEvents = [Projapi.Links.Navigation.FetchFirst, Projapi.Links.Navigation.FetchNext,
		Projapi.Links.Navigation.FetchPrev, Projapi.Links.Navigation.FetchLast];
//Projapi.Widgets.PJHTMLBrowse.prototype.NavigationTargetEvents = [Projapi.Links.Navigation.QueryPosition];

Projapi.Widgets.PJHTMLBrowse.prototype._staticMessageBundle = {
	noRecordContent: 'Waiting for data...'
}

/**
 * Private method for initializing the non visual (before createObjects) properties of this object from the 
 * properties parameter passed in the constructor
 * @private 
 */
Projapi.Widgets.PJHTMLBrowse.prototype._processObjectProperties = function() {
	Projapi.Widgets.PJHTMLBrowse.superclass._processObjectProperties.call(this);
}


/**
 * Private method for initializing the visual properties (after createObjects) of this object from the properties
 * parameter passed in the constructor
 * @private 
 */
Projapi.Widgets.PJHTMLBrowse.prototype._processVisualObjectProperties = function() {
	Projapi.Widgets.PJHTMLBrowse.superclass._processVisualObjectProperties.call(this);
	var width = this._properties.width || null, height = this._properties.height || null;
	if (width || height)
		this.setSize(width, height);
	if (this._dataSource) {
		this._expectCacheChange = true;
		this.newBatch();
	}
	if (this._properties.hidden || this._properties.hideOnInit)
		this.hideObject();	
}


/**
 * Performs general initialization common to all objects.
 */
Projapi.Widgets.PJHTMLBrowse.prototype.createObjects = function() { 
	if (this._objectCreated) return;
	this._objectCreated = true;
	this._processObjectProperties();
	this._buildUI();
	var oThis = this;
	
	if (this._properties.createToolbar) {
		this.toolbar = new Projapi.Widgets.PJToolbar(this._objectName + '-generated-toolbar', {});
		this.toolbar.addLink(Projapi.Links.Container.CreateObjects, new Projapi.Widgets.PJToolButton(this._objectName + '-generated-tbFirst', {
			label: '|<',
			onClickExecute: function(){ oThis.fetchFirst(); }}));
		this.toolbar.addLink(Projapi.Links.Container.CreateObjects, new Projapi.Widgets.PJToolButton(this._objectName + '-generated-tbPrev', {
			label: '<',
			onClickExecute: function(){ oThis.fetchPrev(); }}));
		this.toolbar.addLink(Projapi.Links.Container.CreateObjects, new Projapi.Widgets.PJToolButton(this._objectName + '-generated-tbNext', {
			label: '>',
			onClickExecute: function(){ oThis.fetchNext(); }}));
		this.toolbar.addLink(Projapi.Links.Container.CreateObjects, new Projapi.Widgets.PJToolButton(this._objectName + '-generated-tbLast', {
			label: '>|',
			onClickExecute: function(){ oThis.fetchLast(); }}));
		this.addLink(Projapi.Links.Container.CreateObjects, this.toolbar);
		this.toolbar.createObjects();
	}
	
	this._makeContentFunction();
}


/**
 * Builds the UI
 * @private 
 */
Projapi.Widgets.PJHTMLBrowse.prototype._buildUI = function() {
	var _node;
	
	if( !this._domNode ) {
		this.setDOMNode(Projapi.UI.Element.fromString('<div id="' + this._objectName + '" class="htmlBrowse"><div class="htmlBrowseContent"></div></div>'));
		this._contentDOMNode = this._domNode.domNode.firstChild;
		
		if( this.getContainerSource() ) { 
			var _layoutManager = this.getContainerSource().getLayoutManager(this.getObjectPage());
			if( _layoutManager ) _layoutManager.add(this);
		}
		
	}	
}


/**


/**
 * Performs general initialization common to all objects.
 */
Projapi.Widgets.PJHTMLBrowse.prototype.initializeObject = function() { 
	if (this._objectInitialized) return;
	Projapi.Widgets.PJHTMLBrowse.superclass.initializeObject.call(this);					
	this._objectInitialized = true;
	this._processVisualObjectProperties();
	if (this.toolbar) this.toolbar.initializeObject();
}


Projapi.Widgets.PJHTMLBrowse.prototype.getLayoutManager = function() {
	return {node: this._domNode.domNode,
		add: function(obj) {
			this.node.insertBefore(obj.getDOMNode().domNode, this.node.lastChild);
		},
		remove: function(obj) {
			this.node.removeChild(obj.getDOMNode().domNode);
		}}
}


Projapi.Widgets.PJHTMLBrowse.prototype.setSize = function(width, height) {	
	if( typeof width != 'undefined' && width !== null ) {
		this._properties.width = width;
		if( this._domNode ) {
			this._domNode.setWidth(width);
		}
	}
	
	if( typeof height != 'undefined' && height !== null ) {
		this._properties.height = height;
		if( this._domNode ) {
			this._domNode.setHeight(height);
		}
	}	
}

Projapi.Widgets.PJHTMLBrowse.prototype.getDataSource = function() {
	return this._dataSource;
}

Projapi.Widgets.PJHTMLBrowse.prototype.setDataSource = function(dO) {
	this._dataSource = dO;
	var oldHook = dO._properties.onCacheChange;
	var oThis = this;
	dO._properties.onCacheChange = function() {
		if (oldHook)
			oldHook();
		oThis.newBatch();
	}
	
	if (this._objectCreated)
		this._makeContentFunction();
	
	if (dO && this._objectInitialized) {
		this._expectCacheChange = true;
		this.newBatch();
	}
}

Projapi.Widgets.PJHTMLBrowse.prototype.getNavigationSource = function() {
	return this._navigationSource;
}

Projapi.Widgets.PJHTMLBrowse.prototype.setNavigationSource = function(navSrc) {
	this._navigationSource = navSrc;
	if (navSrc && this._objectCreated)
		this.publishQueryPos();
}

Projapi.Widgets.PJHTMLBrowse.prototype.newBatch = function() {
	if (this._expectCacheChange)
		this.paint();
	else {
		console.warn("DataObject changed batch unexpectedly, going to first position.");
		this.fetchFirst();
	}
}

Projapi.Widgets.PJHTMLBrowse.prototype.paint = function() {
	var content, dO = this._dataSource._getDataObject();
	if (dO.cache.length == 0)
		content = this.getMessage('noRecordContent');
	else {
		content = [];
		if (this._properties.position < 0)
			this._properties.position += dO.cache.length;
		var names = dO.options.columns, end = this._properties.position + this._properties.pageSize;
		for (var i = this._properties.position; i < dO.cache.length && i < end; i++)
			content.push(this._contentFunction(dO.cache[i]));
		content = this._properties.contentBefore + content.join(this._properties.contentSeparator) + this._properties.contentAfter;
	}
	this._contentDOMNode.innerHTML = content;
	this.publishQueryPos();
}

Projapi.Widgets.PJHTMLBrowse.prototype.publishQueryPos = function() {
	this.publish(Projapi.Links.Navigation.QueryPosition, this.getQueryPosition());
}

Projapi.Widgets.PJHTMLBrowse.prototype.getQueryPosition = function() {
	var dO = this._dataSource._getDataObject(), fr = dO.options.hasFirstRow, lr = dO.options.hasLastRow;
	if (dO.cache.length == 0)
		return "NoRecordAvailable";
	else if (fr && lr && dO.cache.length <= this._properties.pageSize)
		return "OnlyRecordAvailable";
	else if (fr && this._properties.position == 0)
		return "FirstRecord";
	else if (lr && this._properties.position + this._properties.pageSize >= dO.cache.length)
		return "LastRecord";
	else
		return "NotFirstOrLast";
}

Projapi.Widgets.PJHTMLBrowse.prototype.fetchFirst = function() {
	this._properties.position = 0;
	if (this._dataSource._properties.hasFirstRow) {
		this.paint();
	} else {
		this._expectCacheChange = true;
		this._dataSource.fetchFirst();
	}
}

Projapi.Widgets.PJHTMLBrowse.prototype.fetchPrev = function() {
	this._properties.position -= this._properties.pageSize;
	if (this._properties.position < 0)
		if (this._dataSource._properties.hasFirstRow) {
			this._properties.position = 0;
			this.paint();
		} else {
			var pos = this._properties.position + this._properties.pageSize;
			var dO = this._dataSource._getDataObject();
			this._properties.position = -this._properties.pageSize;
			this._expectCacheChange = true;
			dO.getBatch(dO.cache[pos][dO.options.columns.indexByName.rowid].value, -1, true);
		}
	else
		this.paint();
}

Projapi.Widgets.PJHTMLBrowse.prototype.fetchNext = function() {
	this._properties.position += this._properties.pageSize;
	var dO = this._dataSource._getDataObject();
	if (this._properties.position + this._properties.pageSize > dO.cache.length && !dO.options.hasLastRow) {
		var pos = this._properties.position - this._properties.pageSize;
		this._properties.position = 0;
		this._expectCacheChange = true;
		dO.getBatch(dO.cache[pos][dO.options.columns.indexByName.rowid].value, 1, true);
	} else if (this._properties.position > dO.cache.length && dO.options.hasLastRow)
		this._properties.position -= this._properties.pageSize;
	else
		this.paint();
}

Projapi.Widgets.PJHTMLBrowse.prototype.fetchLast = function() {
	if (this._dataSource._properties.hasLastRow) {
		this._properties.position = this._dataSource._getDataObject().cache.length-this._properties.pageSize;
		this.paint();
	} else {
		this._properties.position = -this._properties.pageSize;
		this._expectCacheChange = true;
		this._dataSource.fetchLast();
	}
}

Projapi.Widgets.PJHTMLBrowse.prototype.setContentBody = function(newContentTemplate) {
	if (typeof newContentTemplate != 'string')
		throw new Error("contentBody must be a string!");
	this._properties.contentBody = newContentTemplate;
	this._makeContentFunction();
	this.paint();
}

Projapi.Widgets.PJHTMLBrowse.prototype._makeContentFunction = function() {
	var oThis = this, m;
	if (!this._dataSource) {
		this._contentFunction = function() {
			return "No DataSource linked to HTMLBrowse";
		}
		return;
	}
	var cols = this._dataSource._properties.columns;
	var str = '"' + this._properties.contentBody.replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"';
	while (m = str.match(/{[^}]*({([-0-9a-zA-Z_]+)})/))
		if (typeof cols.indexByName[m[2]] == 'number')
			str = str.replace(m[1], 'row[' + cols.indexByName[m[2]] + '].value');
		else
			str = str.replace(m[1], '"column \\"' + m[2] + '\\" not found"');
	while (m = str.match(/{([-0-9a-zA-Z_]+)}/))
		if (typeof cols.indexByName[m[1]] == 'number')
			str = str.replace(m[0], '" + row[' + cols.indexByName[m[1]] + '].value + "');
		else
			str = str.replace(m[0], '(column \\"' + m[1] + '\\" not found)');
	while (m = str.match(/{(.*?)}/))
		str = str.replace(m[0], '" + (' + m[1].replace(/\\"/g, '"').replace(/\\\\/g, '\\') + ') + "');
	
	try {
		eval('oThis._contentFunction = function(row) { return ' + str + '}');
	} catch(e) {
		console.error("Unable to compile contentBody for %s: %o, string was: %s", this._objectName, e, str);
		this._contentFunction = function() {
			return "Error while compiling contentBody.";
		}
	}
}
