/**
 * @class	CS_Window
 * @author	Paul Kruijt
 */
var CS_Window = new Class(
{
	/**
	 * Constructor
	 * @param	string	id
	 * @return	void
	 */
	initialize: function(id)
	{
		// properties
		this.id	= !id ? null : id;
		
		// nodes
		this.document_node	= document.getElement('body');
		
		// classes
		this.class_root_wrapper			= 'cs_window_wrapper';
		this.class_root					= 'cs_window';
		this.class_shadow_top_left		= 'cs_window_shadow_top_left';
		this.class_shadow_top			= 'cs_window_shadow_top';
		this.class_shadow_top_right		= 'cs_window_shadow_top_right';
		this.class_shadow_right			= 'cs_window_shadow_right';
		this.class_shadow_bottom_right	= 'cs_window_shadow_bottom_right';
		this.class_shadow_bottom		= 'cs_window_shadow_bottom';
		this.class_shadow_bottom_left	= 'cs_window_shadow_bottom_left';
		this.class_shadow_left			= 'cs_window_shadow_left';		
		this.class_header_wrapper		= 'cs_window_header_wrapper';
		this.class_header				= 'cs_window_header';
		this.class_header_text			= 'cs_window_header_text';
		this.class_content_wrapper		= 'cs_window_content_wrapper';
		this.class_content				= 'cs_window_content';
		this.class_footer_wrapper		= 'cs_window_footer_wrapper';
		this.class_footer				= 'cs_window_footer';
		this.class_statusbar_wrapper	= 'cs_window_statusbar_wrapper';
		this.class_statusbar			= 'cs_window_statusbar';
		this.class_icon_minimize		= 'cs_window_icon_minimize';
		this.class_icon_maximize		= 'cs_window_icon_maximize';
		this.class_icon_close			= 'cs_window_icon_close';
		this.class_resize_handler		= 'cs_window_resize_handler';
		
		// event objects
		this.event_drag		= null;
		this.event_resize	= null;
		
		// settings
		this.minimum_height			= 150;
		this.minimum_width			= 150;
		this.stacking_multiplier	= 100;
		
		// create window
		this.createRoot();
	},
	
	/**
	 * create root of window
	 * @return	void
	 */
	createRoot: function()
	{
		// set vars
		var _this = this;
		
		if (this.document_node)
		{
			// set id
			if (!this.id) this.setId();
			
			this.root_wrapper_node = new Element('div',
			{
				'id'		: this.id,
				'class'		: this.class_root_wrapper
			});
			
			this.root_node = new Element('div',
			{
				'class'	: this.class_root
			});
			
			// inject nodes
			this.root_wrapper_node.inject(this.document_node);
			this.root_node.inject(this.root_wrapper_node);
			
			// always set stacking order
			this.setStacking();
			
			// always create a close button
			this.createIconClose();
			
			// always create content
			this.createContent();
			
			// always set these events
			this.root_wrapper_node.removeEvents();
			this.root_wrapper_node.addEvents(
			{
				'mousedown'	: function()
				{
					_this.setFocus();
				}
			});
		}
	},
	
	/**
	 * create header
	 * @return	void
	 */
	createHeader: function()
	{
		if (this.root_node)
		{
			var header_wrapper_node	= this.root_node.getElement('.'+this.class_header_wrapper);
			
			if (!header_wrapper_node)
			{
				this.header_wrapper_node = new Element('div',
				{
					'class'	: this.class_header_wrapper
				});
				
				this.header_node = new Element('div',
				{
					'class'	: this.class_header
				});
				
				this.header_text_node = new Element('div',
				{
					'class'	: this.class_header_text
				});
				
				// inject nodes
				this.header_wrapper_node.inject(this.root_node);
				this.header_node.inject(this.header_wrapper_node);
				this.header_text_node.inject(this.header_node);
				
				// reposition content
				this.positionContent();
			}
		}
	},
	
	/**
	 * create content
	 * @return	void
	 */
	createContent: function()
	{
		if (this.root_node)
		{
			var content_wrapper_node	= this.root_node.getElement('.'+this.class_content_wrapper);
			
			if (!content_wrapper_node)
			{
				this.content_wrapper_node = new Element('div',
				{
					'class'	: this.class_content_wrapper
				});
				
				this.content_node = new Element('div',
				{
					'class'	: this.class_content
				});
				
				// inject nodes
				this.content_wrapper_node.inject(this.root_node);
				this.content_node.inject(this.content_wrapper_node);
				
				// position content
				this.positionContent();
			}
		}
	},
	
	/**
	 * create footer
	 * @return	void
	 */
	createFooter: function()
	{
		if (this.root_node)
		{
			var footer_wrapper_node	= this.root_node.getElement('.'+this.class_footer_wrapper);
			
			if (!footer_wrapper_node)
			{
				this.footer_wrapper_node = new Element('div',
				{
					'class'	: this.class_footer_wrapper
				});
				
				this.footer_node = new Element('div',
				{
					'class'	: this.class_footer
				});
				
				// inject nodes
				this.footer_wrapper_node.inject(this.root_node);
				this.footer_node.inject(this.footer_wrapper_node);
				
				// reposition content
				this.positionContent();
			}
		}
	},
	
	/**
	 * create icon close
	 * @return	void
	 */
	createIconClose: function()
	{
		// set vars
		var _this = this;
		
		if (this.root_node)
		{
			var icon_close_node	= this.root_node.getElement('.'+this.class_icon_close);
			
			if (!icon_close_node)
			{
				this.icon_close_node = new Element('a',
				{
					'href'		: '#',
					'class'		: this.class_icon_close,
					'events'	:
					{
						'click'	: function()
						{
							_this.remove();
							
							return false;
						},
						
						'focus'	: function()
						{
							this.blur();
						}
					}
				});
				
				// inject nodes
				this.icon_close_node.inject(this.root_node);
			}
		}
	},
	
	/**
	 * create resize handler
	 * @return	void
	 */
	createResizeHandler: function()
	{
		if (this.footer_node && !this.resize_handler_node)
		{
			this.resize_handler_node = new Element('div',
			{
				'class'	: this.class_resize_handler
			});
			
			// inject nodes
			this.resize_handler_node.inject(this.footer_node);
		}
	},
	
	/**
	 * position content
	 * @return	void
	 */
	positionContent: function()
	{
		if (this.content_wrapper_node)
		{
			// set vars
			var header_height	= 0;
			var footer_height	= 0;
			
			// check for header
			if (this.header_wrapper_node)
			{
				var header_height_coordinates	= this.header_wrapper_node.getCoordinates();
				header_height					= header_height_coordinates.height.toInt();
			}
			
			// check for footer
			if (this.footer_wrapper_node)
			{
				var footer_height_coordinates	= this.footer_wrapper_node.getCoordinates();
				footer_height					= footer_height_coordinates.height.toInt();
			}
			
			// set new position
			this.content_wrapper_node.setStyles(
			{
				'top'		: header_height+'px',
				'bottom'	: footer_height+'px'
			});
		}
	},
	
	/**
	 * set id
	 * @param	string	str_id
	 * @return	void
	 */
	setId: function(str_id)
	{
		// generate id (if function exists)
		if (!str_id && typeof window.generateRandomString == 'function')
		{
			this.id = 'cs_window_'+generateRandomString(40);
		}
		
		// use given id
		else if (str_id)
		{
			this.id = str_id;
		}
		
		// include function from the right file
		else
		{
			alert("Calling non existing function: \"generateRandomString()\".\nPlease include \"CS_functions.js\" from Cymeq Library.");
		}
	},
	
	/**
	 * set header
	 * @param	string	text
	 * @return	void
	 */
	setHeader: function(text)
	{
		// check if header exist
		if (!this.header_wrapper_node)
		{
			this.createHeader();
		}
		
		// set header text
		if (this.header_text_node)
		{
			this.header_text_node.set('text', text);
		}
	},
	
	/**
	 * set content
	 * @param	string	str_html
	 * @return	void
	 */
	setContent: function(str_html)
	{
		if (this.content_node && str_html)
		{
			this.content_node.innerHTML = str_html;
		}
	},
	
	/**
	 * set footer
	 * @return	void
	 */
	setFooter: function()
	{
		// check if footer exist
		if (!this.footer_wrapper_node)
		{
			this.createFooter();
		}
		
		// maybe set some buttons here...
	},
	
	/**
	 * set size
	 * @param	integer	width
	 * @param	integer	height
	 * @return	void
	 */
	setSize: function(width, height)
	{
		var width	= !width ? 0 : width.toInt();
		var height	= !height ? 0 : height.toInt();
		
		if (width > 0)	this.setWidth(width);
		if (height > 0)	this.setHeight(height);
	},
	
	/**
	 * set width
	 * @param	integer	width
	 * @return	void
	 */
	setWidth: function(width)
	{
		var width	= !width ? 0 : width.toInt();
		
		if (width > 0)
		{
			if (this.root_wrapper_node)
			{
				this.root_wrapper_node.setStyle('width', width+'px');
			}
		}
	},
	
	/**
	 * set height
	 * @param	integer	height
	 * @return	void
	 */
	setHeight: function(height)
	{
		var height	= !height ? 0 : height.toInt();
		
		if (height > 0)
		{
			if (this.root_wrapper_node)
			{
				this.root_wrapper_node.setStyle('height', height+'px');
			}
		}
	},
	
	/**
	 * set stacking
	 * @return void
	 */
	setStacking: function()
	{
		if (this.root_wrapper_node)
		{
			// get all windows
			var window_nodes		= this.document_node.getElements('.'+this.class_root_wrapper);
			var total_window_nodes	= window_nodes.length;
			
			if (total_window_nodes > 0)
			{
				var z_index	= (total_window_nodes * this.stacking_multiplier).toInt();
				
				// set z-index
				this.root_wrapper_node.setStyle('z-index', z_index);
			}
		}
	},
	
	/**
	 * load content (http request)
	 * @param	string	request_url (complete with parameters)
	 * @return	void
	 */
	loadContent: function(request_url)
	{
		// set vars
		var _this = this;
		
		// make request
		if (this.content_node && request_url)
		{
			var http_request = new Request.HTML(
			{
				url			: request_url,
				update		: this.content_node,
				onRequest	: function()
				{
					
				},
				onComplete	: function()
				{
					// set content events
					_this.setContentEvents();
				}
			});
			
			http_request.get();
		}
	},
	
	/**
	 * set content events
	 * @return	void
	 */
	setContentEvents: function()
	{
		// empty method. extend cs_window class and place this method in that class for specific events
	},
	
	/**
	 * enable shadow
	 * @return	void
	 */
	enableShadow: function()
	{
		if (this.root_wrapper_node)
		{
			// create nodes
			this.shadow_top_left_node		= new Element('div', {'class' : this.class_shadow_top_left});
			this.shadow_top_node			= new Element('div', {'class' : this.class_shadow_top});
			this.shadow_top_right_node		= new Element('div', {'class' : this.class_shadow_top_right});
			this.shadow_right_node			= new Element('div', {'class' : this.class_shadow_right});
			this.shadow_bottom_right_node	= new Element('div', {'class' : this.class_shadow_bottom_right});
			this.shadow_bottom_node			= new Element('div', {'class' : this.class_shadow_bottom});
			this.shadow_bottom_left_node	= new Element('div', {'class' : this.class_shadow_bottom_left});
			this.shadow_left_node			= new Element('div', {'class' : this.class_shadow_left});
			
			// inject nodes
			this.shadow_top_left_node.inject(this.root_wrapper_node);
			this.shadow_top_node.inject(this.root_wrapper_node);
			this.shadow_top_right_node.inject(this.root_wrapper_node);
			this.shadow_right_node.inject(this.root_wrapper_node);
			this.shadow_bottom_right_node.inject(this.root_wrapper_node);
			this.shadow_bottom_node.inject(this.root_wrapper_node);
			this.shadow_bottom_left_node.inject(this.root_wrapper_node);
			this.shadow_left_node.inject(this.root_wrapper_node);
		}
	},
	
	/**
	 * enable toggle
	 * @return	void
	 */
	enableToggle: function()
	{
		// set vars
		var _this = this;
		
		if (this.header_wrapper_node)
		{
			// first remove events and then set them again
			this.header_wrapper_node.removeEvents();
			this.header_wrapper_node.addEvents(
			{
				'dblclick'	: function()
				{
					// toggle content
					if (_this.content_wrapper_node)
					{
						var content_display_current	= _this.content_wrapper_node.getStyle('display');
						var content_display_new		= content_display_current == 'none' ? 'block' : 'none';
						
						_this.content_wrapper_node.setStyle('display', content_display_new);
					}
					
					// toggle footer
					if (_this.footer_wrapper_node)
					{
						var footer_display_current	= _this.footer_wrapper_node.getStyle('display');
						var footer_display_new		= footer_display_current == 'none' ? 'block' : 'none';
						
						_this.footer_wrapper_node.setStyle('display', footer_display_new);
					}
				}
			});
		}
		else
		{
			alert('Please create the header before you enable the toggle event.');
		}
	},
	
	/**
	 * enable drag
	 * @return void
	 */
	enableDrag: function()
	{
		// set vars
		var _this = this;
		
		if (this.root_wrapper_node && this.header_node)
		{
			// set limits
			var document_width	= window.getWidth();
			var document_height	= window.getHeight();
			
			var window_width	= this.root_wrapper_node.getWidth();
			var window_height	= this.root_wrapper_node.getHeight();
			
			var shadow_width	= 0;
			var shadow_height	= 0;
			
			// get size of shadow
			if (this.shadow_right_node)
			{
				var shadow_right_coordinates	= this.shadow_right_node.getCoordinates();
				shadow_width					= shadow_right_coordinates.width.toInt();
				shadow_height					= shadow_width;
			}
			
			var limit_x	= document_width - window_width - shadow_width;
			var limit_y	= document_height - window_height - shadow_height;
			
			// first always detach the event if there is any
			if (this.event_drag) this.event_drag.detach();
			
			// start drag event
			this.event_drag = new Drag(this.root_wrapper_node,
			{
				snap		: 0,
				handle		: this.header_node,
				limit		: {x:[shadow_width, limit_x], y:[shadow_height, limit_y]},
				onComplete	: function()
				{
					// re-init resize event
					_this.enableResize();
				}
			});
		}
	},
	
	/**
	 * enable resize
	 * @return void
	 */
	enableResize: function()
	{
		// set vars
		var _this = this;
		
		if (this.root_wrapper_node)
		{
			// create resize handler
			this.createResizeHandler();
			
			if (this.resize_handler_node)
			{
				// set limits
				var document_width				= window.getWidth();
				var document_height				= window.getHeight();
				var root_wrapper_coordinates	= this.root_wrapper_node.getCoordinates();
				root_wrapper_left				= root_wrapper_coordinates.left.toInt();
				root_wrapper_top				= root_wrapper_coordinates.top.toInt();
				
				var shadow_width	= 0;
				var shadow_height	= 0;
				
				// get size of shadow
				if (this.shadow_right_node)
				{
					var shadow_right_coordinates	= this.shadow_right_node.getCoordinates();
					shadow_width					= shadow_right_coordinates.width.toInt();
					shadow_height					= shadow_width;
				}
				
				var limit_x_first	= this.minimum_width;
				var limit_x_second	= document_width - root_wrapper_left - shadow_width;
				var limit_y_first	= this.minimum_height;
				var limit_y_second	= document_height - root_wrapper_top - shadow_height;
				
				
				// first always detach the event if there is any
				if (this.event_resize)
				{
					this.event_resize.detach();
				}
				
				this.event_resize = this.root_wrapper_node.makeResizable(
				{
					handle		: this.resize_handler_node,
					limit		: {x:[limit_x_first, limit_x_second], y:[limit_y_first, limit_y_second]},
					onComplete	: function()
					{
						// re-init drag event
						_this.enableDrag();
					}
				});
			}
		}
	},
	
	/**
	 * set focus
	 * @return	void
	 */
	setFocus: function()
	{
		// set vars
		var _this = this;

		// get all windows
		var window_nodes		= this.document_node.getElements('.'+this.class_root_wrapper);
		var total_window_nodes	= window_nodes.length;
		
		if (total_window_nodes > 0)
		{
			// get last window node and check if it the current window
			var last_window_node	= window_nodes.getLast();
			
			if (last_window_node)
			{
				var last_window_id = last_window_node.get('id');
				
				if (last_window_id != this.id)
				{
					// first move focussed window last in line
					this.document_node.grab(this.root_wrapper_node);
					
					// get all windows
					var window_nodes		= this.document_node.getElements('.'+this.class_root_wrapper);
					var total_window_nodes	= window_nodes.length;
					
					if (total_window_nodes > 0)
					{
						window_nodes.each(function(window_node, index)
						{
							var window_nr	= index + 1;
							var z_index		= (window_nr * _this.stacking_multiplier).toInt();
							
							// set z-index
							window_node.setStyle('z-index', z_index);
						});
					}
				}
			}
		}
	},
	
	/**
	 * show window
	 * @return	void
	 */
	show: function()
	{
		if (this.root_wrapper_node) this.root_wrapper_node.setStyle('visibility', 'visible');
	},
	
	/**
	 * hide window
	 * @return	void
	 */
	hide: function()
	{
		if (this.root_wrapper_node) this.root_wrapper_node.setStyle('visibility', 'hidden');
	},
	
	/**
	 * remove window
	 * @return	void
	 */
	remove: function()
	{
		if (this.root_wrapper_node) this.root_wrapper_node.dispose();
	}

});
