//*************************************************************************************************
/*!
	\file		Solera.js
	\brief		Main decfinitions
	\par    	Project:
					Solera 0.01
	\par		Copyright:
					PATANEGRA Soft  												<br>
					Sevilla (SPAIN) 												<br>
					<a href="http://www.patanegra.com">http://www.patanegra.com</a>	<br>
					Aug 2003
*/
//*************************************************************************************************

//*************************************************************************************************
/*!
	\brief		Class: Clean system services (without solera dependencies) for solera objects
	\internal
	\date			Aug 2005 - AGS
*/
//*************************************************************************************************
function SlSys()
{
	// Get document head
	SlSys._head = document.getElementsByTagName('head')[0];

	// Get document body: Useful for SlSys._body.clientWidth/clientHeight (for physical use screen.width/height)
	SlSys._body = document.getElementsByTagName('body')[0];

	//! Get document protocol (including //)
	SlSys._proto = document.location.protocol + '//';

	// CrossBrowsing: detect browsers
	SlSys._ua     = navigator.userAgent.toLowerCase()
	SlSys._safari = SlSys._ua.indexOf("safari") > -1;
	SlSys._opera  = SlSys._ua.indexOf("opera") > -1;
	SlSys._ns     = !SlSys._opera && !SlSys._safari && (navigator.appName == "Netscape");
	SlSys._ie     = !SlSys._opera && (navigator.appName == "Microsoft Internet Explorer");
	SlSys._gecko  = SlSys._ua.indexOf('gecko') > -1;
}

//! "Clean" system services initialization
SlSys();

//*************************************************************************************************
/*!
	\brief		Method: Configure inheritance for a class
	\param		motherclass A direct reference to the mother class
	\return		The own object
	\internal
	\date			Oct 2003 - Douglas Crockford
	\date			Dec 2003 - AGS
*/
//*************************************************************************************************
Function.prototype.inherits = function(motherclass)
{
	// Sets new prototype object
   this.prototype = new motherclass;

	// Get name of the class
	var __classname = this.toString();
	__classname = __classname.substr(0, __classname.indexOf('(')).split(' ')[1];

	//! Method: Returns Solera class name
	this.getClassName = this.prototype.getClassName = function()
	{
		return __classname;
	}

	//! Method: Returns if the object/class descends from a Solera class name
	this.descendsFrom = this.prototype.descendsFrom = function(cn)
	{
		return __classname == cn || (motherclass.descendsFrom ? motherclass.descendsFrom(cn) : cn == 'Function');
   	}

   return this;
}

//! Set inheritance
SlBase.inherits(Function);

//*************************************************************************************************
/*!
	\brief		Class: Solera base class
	\param		id Object identifier (null for automatic)
	\par			Comment:
						- All vars leading _ (single underscore) will be considered as public, readable, non writable<br>
						- All vars leading __ (double underscore)  will be considered as private, non readable, non writable<br>
						- All the rest of vars will be considered as public, readable, writable
						- All methods will be considered public, readable, writable, executable<br>
	\internal
	\date			Sep 2003 - AGS
*/
//*************************************************************************************************
function SlBase(id)
{
	// Automatic id generation: classname + counter
	if(id == null)
	{
		// Catch object classname
		var s = this.getClassName();

		// Check for class counter array
		if(SlBase.__counters == null)
			SlBase.__counters = new Object;

		// Check for class counter value
		if(SlBase.__counters[s] == null)
			SlBase.__counters[s] = 0;

		// Default id for objects
		id = s + SlBase.__counters[s]++;
	}

	// Attributes
	this._id     = id;  	   //!< Id
	this._status = new Object; //!< Object status

	// Check for objects array
	if(SlBase.__all == null)
		SlBase.__all = new Object;

	// Check id duplicates
	if(SlBase.__all[id] != null)
		throw 'context=[SlBase()] class=[' + this.getClassName() + '] what=[Identifier \"' + id + '\" already declared]';

	// Index solera object
	SlBase.__all[id] = this;
}

//*************************************************************************************************
/*!
	\brief		Method: Default message processing
	\param		msg Message sent
	\return		true if \a msg was processed, false if not
	\internal
	\date			Jun 2005 - AGS
*/
//*************************************************************************************************
SlBase.prototype.msgDefault = function(msg)
{
	switch(msg.getClassName())
	{
		case 'SlMsgEval':
			eval('(' + msg._expr + ')');
			break;

		case 'SlMsgFunction':
			msg._fnref(msg._params);
			break;

		case 'SlMsgSend':
			SlHttpRequest(msg._srv, msg._data, msg._cba = this);
			break;

		case 'SlMsgRecv':
			SlDebug(msg._data.length + " bytes: " + msg._data.substr(0, 20) + " ... " + msg._data.substr(msg._data.length-20));
			break;

		default:
			throw 'context=[SlBase.msgDefault()] class=[' + this.getClassName() + '] what=[Cant\'t process message of type \"' + msg.getClassName() + '\"]';
	}

	return true;
}

//*************************************************************************************************
/*!
	\brief		Method: Destroy object
	\internal
	\date			Dec 2003 - AGS
*/
//*************************************************************************************************
SlBase.prototype.destroy = function()
{
	// Unregister object
	SlBase.__all[this._id] = null;
}

//*************************************************************************************************
/*!
	\brief		Method: Return value for a statys type
	\param		stype Status type
	\return		The value of the status for \a stype
	\internal
	\date			Oct 2003 - AGS
*/
//*************************************************************************************************
SlBase.prototype.getStatus = function(stype)
{
	return this._status[stype];
}

//*************************************************************************************************
/*!
	\brief		Method: Sets the value for a status type
	\param		stype  Status name / Array of status names
	\param		svalue Status value / Array of new status values
	\return		The new value or the first new value if use arrays
	\par			Comment:
					If \a stype is an array, \a svalue must be another one
	\internal
	\date			Oct 2003 - AGS
*/
//*************************************************************************************************
SlBase.prototype.setStatus = function(stype, svalue)
{
	if(typeof(stype) == 'object')
	{
		for(var x = 0; x < stype.length; x++)
			this._status[stype[x]] = svalue[x];
		return svalue[0];
	}
	else
	{
		return this._status[stype] = svalue;
	}
}

//*************************************************************************************************
/*!
	\brief		Method: Sets the value for a status type if not previously stablished
	\param		stype  Status name / Array of status names
	\param		svalue Status value / Array of new status values
	\return		The new value or the first new value if use arrays
	\par			Comment:
					If \a stype is an array, \a svalue must be another one
	\internal
	\date			Oct 2003 - AGS
*/
//*************************************************************************************************
SlBase.prototype.setStatusDefault = function(stype, svalue)
{
	if(typeof(stype) == 'object')
	{
		for(var x = 0; x < stype.length; x++)
			if(this._status[stype[x]] == null)
				this._status[stype[x]] = svalue[x];
		return svalue[0];
	}
	else
	{
		if(this._status[stype] == null)
			return this._status[stype] = svalue;
		return this._status[stype];
	}
}

//! Set inheritance
SlModule.inherits(SlBase);

//*************************************************************************************************
/*!
	\brief		Class: Development
	\param		id		  Id for instance, not null for singleton module vars
	\param		path    Access path
	\param		culture Culture
	\param		theme   Theme
	\internal
	\date			Aug 2003 - AGS
*/
//*************************************************************************************************
function SlModule(id, path, culture, theme)
{
	// Needed for inherits method. DON'T REMOVE!!!
	if(arguments.length == 0)
		return;

	// Mother class ctor, module instances are singletones due to unique ids
	SlBase.call(this, id);

	// For Initialize in constructors
	this._name     = null; //!< Name
	this._version  = null; //!< Versión
	this._created  = null; //!< Date creation
	this._updated  = null; //!< Date modification
	this._license  = null; //!< License type
	this._company  = null; //!< Company
	this._web 	   = null; //!< Web
	this._team     = null; //!< Developer team

	this._path     = path    ? path    : ''       ; //!< Path to resources and files
	this._culture  = culture ? culture : 'Default'; //!< Culture
	this._theme    = theme   ? theme   : 'Default'; //!< Theme

	//! Possible status for whole application: use, design
	this._status['runmode'] = 'use';
}

//*************************************************************************************************
/*!
	\brief		Method: Gets a resource by its type and name
	\param		type Type
	\param		name Name
	\return  	A variable type with the wanted resource
	\par			Comment:
						Types supported:                       \n
						\b img   Theme image                   \n
						\b imgnt Non theme image               \n
						\b css   Theme css                     \n
						\b theme Theme configuraton javascript \n
						\b str   Culture string                \n
						\b js		Javascript source              \n
	\internal
	\date			Aug 2005 - AGS
*/
//*************************************************************************************************
SlModule.prototype.getResource = function(type, name)
{
	switch(type)
	{
		case 'img'  : return this._path + '_Themes/' + this._theme + '/_Res/' + name;
		case 'imgnt': return this._path + '_Res/' + name;

		// CrossBrowsing: gecko needs an unique title string in css loading, don't use more than one!
		case 'css'  : return '<link type="text/css" rel="stylesheet" href="' + this._path + '_Themes/' + this._theme + '/_Css/' + name + '" title="' + document.location.href + '">';

		case 'theme': return '<' + 'script language="JavaScript" src="' + this._path + '_Themes/' + this._theme + '/' + name + '"><' + '/script' + '>';
		case 'str'  : return name; //zz need implement this!
		case 'js'   : return '<' + 'script type="text/javascript" src="' + this._path + name + '"><' + '/script' + '>';
		default     : throw  'context=[SlModule.prototype.getResource()] what=[Unknown type \"' + type + '\"]';
	}
}

//*************************************************************************************************
/*!
	\brief		Method: Include file by its resource type and name
	\param		type Type
	\param		name Name
	\par			Comment:
						Resource types are the same that in SlModule.getResource() method
	\internal
	\date			Aug 2005 - AGS
*/
//*************************************************************************************************
SlModule.prototype.include = function (type, name)
{
	document.write(this.getResource(type, name));
}

//! Set inheritance
Solera.inherits(SlModule);

//*************************************************************************************************
/*!
	\brief		Class: Solera library environment
	\param		path    Access path
	\param		culture Culture
	\param		theme   Theme
	\internal
	\date			Aug 2005 - AGS
*/
//*************************************************************************************************
function Solera(path, culture, theme)
{
	// Mother class ctor
	SlModule.call(this, this.getClassName(), path, culture, theme);

	// For Initialize in constructors
	this._name     = this.getClassName();
	this._version  = '0.01';
	this._created  = new Date(2003, 8, 18);
	this._updated  = new Date(2006, 2, 20);
	this._license  = 'LGPL';
	this._company  = 'PATANEGRA Soft S.L.';
	this._web 	   = 'www.patanegra.com/Solera';
	this._team     = 'AGS FMD';

	// Nonsystem agent focus: true/false
	this._status['nonsystemfocus'] = false;

	// Solera. js. base
	this.include('js'   , 'SlUtil.js'    	  );

	// Solera. js. interface
	this.include('js'   , 'SlLayer.js'     	  );
	this.include('js'   , 'SlSizer.js'        );
	this.include('js'   , 'SlLayerRelative.js');
}

