/*

	Javascript template object model
	
	Requires ???
	
	Author: Mantzoukas Alexander
	Company: Enorasis S.A.
	Version: 1.0.0.4
	Email: alexander.mantzoukas@enorasis.com

*/

/*
	{
		Tag : string,
		[ elementProperty / styleProperty ] : string,
		[ e_onElementEvent ] : function/event,
		[ w_onWindowEvent ] : function/event,
		[ onUICreate / onUIDestroy / onUIShow / onUIHide / onUIResize ] : function,
		[ NoContents ]: true / false
		[ Property ]: string,
		Contents: [
			[ { _same_ } ],
			...
		]
	}
*/

var UIDrawingPart = new Class();
UIDrawingPart.Declare(
	{
		Definition: new Object(),
		RootElement: null,
		Contents: null,
		
		Constructor: function( obj )
		{
			this.Definition = obj;
		},
		
		Draw: function( root )
		{
			this.Destroy();
			this.Contents = new Array();
			
			root = $element(root);
			this.DrawPart( this.Definition, root );
		},
		
		Redraw: function()
		{
			var root = this.RootElement.parentNode;
			this.Destroy();
			this.Contents = new Array();
			
			root = $element(root);
			this.DrawPart( this.Definition, root );
		},
		
		Destroy: function()
		{
			if (this.RootElement)
			{
				if (this.RootElement.onUIDestroy) this.RootElement.onUIDestroy();
				__GC.GarbageCollectElements( this.RootElement, true );
				this.RootElement.parentNode.removeChild( this.RootElement );
				this.RootElement = null;
			}
		},
		
		DrawPart: function( obj, root )
		{
			var contents = new Array();
			var element = null;
			
			if (!obj['Tag']) return;
			var part = UITemplates.Create( obj['Tag'] );
			
			if (part)
			{
				part.Draw( root );
				contents = part.Contents;
				element = part.RootElement;
			}
			else
			{
				var el = $create( obj['Tag'], root )[0];
				if (!el) return;
				contents = [ el ];
				element = el;
			}
			
			if (!this.RootElement)
			{
				this.RootElement = element;
			}
			if (!part) element.BoundObject = this;
			
			var en = new Enumerator( obj );  
			
			while(en.Next())
			{
				var name = en.PeakName();
				var value = en.Peak();
				
				if (name != 'Tag' && name != 'Contents')
				{
					if (name.indexOf('e_on') == 0 && typeof value == "function")
					{
						name = name.substring( 4, name.length );
						chainEventListener( name, value, element );
					}
					else if (name.indexOf('w_on') == 0 && typeof value == "function")
					{
						name = name.substring( 2, name.length );
						chainWindowEvent( name, Reference(value, element) );
					}
					else if (name == "Property")
					{
						this[ value ] = element;
					}
					else
					{
						try { element[ name ] = value; } catch(e) {};
						try { element.style[ name ] = value; } catch(e) {};
					}
				}
			}
			
			if (obj['Contents'] && obj['Contents'].IsArray)
			{
				for(var i = 0; ( i < contents.length && i < obj['Contents'].length ); ++i)
				{
					if (obj['Contents'][i].IsArray)
					{
						if (!obj['Contents'][i].length)
							this.Contents[ this.Contents.length ] = contents[i];
						else for(var j = 0; j < obj['Contents'][i].length; ++j)
							this.DrawPart( obj['Contents'][i][j], contents[i] );
					}
					else if (!obj['NoContents'])
					{
						this.Contents[ this.Contents.length ] = contents[i];
					}
				}
			}
			else if (!obj['NoContents'])
			{
				for(var i = 0; i < contents.length; ++i)
					this.Contents[ this.Contents.length ] = contents[i];
			}
			
			if (element.onUICreate) element.onUICreate();
			
			return;
		}
	}
);

var UIWarehouse = new Class();
UIWarehouse.Declare(
	{
		Warehouse: new Object(),
		
		Constructor: function()
		{
		},
		
		Register: function( obj, name )
		{
			this.Warehouse[ name ] = obj;
			__GC.markObject(obj);
		},
		
		Unregister: function( name )
		{
			this.Warehouse[ name ] = null;
		},
		
		Create: function( name )
		{
			if (this.Warehouse[ name ])
				return new UIPart( this.Warehouse[ name ] );
			else return null;
		}
	}
);

var UITemplates = new UIWarehouse();
//var UIThemes = new UIWarehouse();
//var UIPhrases = new UIWarehouse();

var UIPart = new Class();
UIPart.Inherit(UIDrawingPart);
UIPart.Declare(
	{
		Wrap: function( element, contentNum )
		{
			var el = $element(element);
			if (!this.RootElement)
			{
				this.Draw( el.parentNode );
			}
			
			el.parentNode.insertBefore( this.RootElement, el );
			this.Contents[ contentNum ].appendChild( el );
		},
		
		Unwrap: function( contentNum )
		{
			if (this.RootElement)
			{
				for(var i = 0; i < this.Contents[ contentNum ].childNodes.length; ++i)
				{
					this.RootElement.parentNode.insertBefore( 
						this.Contents[ contentNum ].childNodes[i], this.RootElement );
				}
			}
		},
		
		Move: function( element, pos )
		{
			if (this.RootElement)
				if (pos == null || typeof pos != 'number')
					$element(element).appendChild( this.RootElement );
				else
					$element(element).insertBefore( this.RootElement, $element(element).childNodes[pos] );
		},
		
		Toggle: function( root )
		{
			if (this.RootElement)
			{
				if (this.RootElement.style.display == "none")
					this.Show();
				else
					this.Hide();
			}
			else if (root)
			{
				this.Draw(root);
			}
		},
		
		Show: function()
		{
			if (this.RootElement)
			{
				if (this.RootElement.onUIShow) this.RootElement.onUIShow();
				this.RootElement.style.display = "";
			}
		},
		
		Hide: function()
		{
			if (this.RootElement)
			{
				if (this.RootElement.onUIHide) this.RootElement.onUIHide();
				this.RootElement.style.display = "none";
			}
		},
		
		GetPosition: function()
		{
			if (this.RootElement)
			{
				var par = this.GetParentPart();
				if (par)
				{
					var pos = [ -1, -1 ];
					for(var i = 0; i < par.Contents.length; ++i)
					{
						if (this.RootElement.parentNode == par.Contents[i])
						{
							pos[0] = i;
							break;
						}
					}
					
					for(var i = 0; i < this.RootElement.parentNode.childNodes.length; ++i)
					{
						if (this.RootElement ==
							this.RootElement.parentNode.childNodes[i])
						{
							pos[1] = i;
							break;
						}
					}
					return pos;
				}
			}
			return null;
		},
		
		GetParentPart: function()
		{
			if (this.RootElement)
			{
				if (this.RootElement.parentNode && this.RootElement.parentNode.BoundObject)
					return this.RootElement.parentNode.BoundObject;
			}
			return null;
		},
		
		GetChildrenParts: function()
		{
			if (this.RootElement)
			{
				var contentsArray = [];
				for(var i = 0; i < this.Contents.length; ++i)
				{
					var children = new Array();
					for(var j = 0; j < this.Contents[i].childNodes.length; ++j)
					{
						if (this.Contents[i].childNodes[j].BoundObject)
							children[ children.length ] = this.Contents[i].childNodes[j].BoundObject;
					}
					contentsArray[ contentsArray.length ] = children;
				}
				
				return contentsArray;
			}
			return null;
		},
		
		Resized: function( sender )
		{
			if (!sender) sender = this;
			if (this.RootElement)
			{
				var parts = this.GetChildrenParts();
				for(var i = 0; i < parts.length; ++i)
				{
					for(var j = 0; j < parts[i].length; ++j)
					{
						if (parts[i][j] != sender &&
							parts[i][j].RootElement.onUIResize)
							parts[i][j].RootElement.onUIResize();
						parts[i][j].Resized( sender );
					}
				}
			}
		}
		/*,
		
		SaveState: function()
		{
		},
		
		LoadState: function( stateStr )
		{
		}*/
	}
);

