/**
* window_manager class
*/

function window_manager(){
	this.error = '';
	this.warning = '';
	
	this.container_class = null;
	this.containers = Array();
	this.containers_assoc = Array();
	this.widgets = Array();
	
	this.widget_settings_handler = null;
	this.on_update = null;
	
	var _self = this;

	/**
	 * Sets the class of the container elements
	 */
	this.set_container_class = function(className){
		_self.container_class = className;
		_self.reload_containers();
	}
	
	/**
	 * makes the widgets dragable
	 */
	_self.dragable = function(){
		$("."+_self.container_class).sortable({
			connectWith: '.'+_self.container_class,
			stop:_self.on_move_stop,
			opacity: 0.6
		});
	}
	
	this.on_move_stop = function(event, ui){
		var widget = _self.get_widget_by_elem_id($(ui.item).attr("id"));
		
		if(typeof(widget)=='object'){
			if(widget.fixedCell){
				var old_container = widget.container;
				var old_position = widget.position;
				widget.update_container();
				var new_container = widget.container;

				if(old_container!=new_container){
					old_container.appendChild(widget.wraper);
					widget.set_position(old_position);
				}
			}
		}
		
		widget.update_container();
		widget.calculate_position();
		
		_self.updated();
	}
	
	/**
	 * sets the function taht will be called for the widget settings
	 * 
	 * @param function settings_handler
	 */
	this.set_settings_handler = function(settings_handler){
		if(typeof(settings_handler)=='function'){
			_self.widget_settings_handler = settings_handler;
		}
		else{
			_self.add_error('given settings handler is not a function');
		}
	}
	
	/**
	 * sets the function taht will be called for the widget position and state update
	 * 
	 * @param function on_update
	 */
	this.set_on_update = function(on_update){
		if(typeof(on_update)=='function'){
			_self.on_update = on_update;
		}
		else{
			_self.add_error('given on_update handler is not a function');
		}
	}
	
	/**
	 * calls on_update function if set
	 */
	this.updated = function(){
		if(typeof(_self.on_update)=='function'){
			positions = _self.get_widgets_positions();
			_self.on_update(positions);
		}
	}
	
	/**
	 * gets the positions of the idgets inside the cells
	 * 
	 * @return object
	 */
	this.get_widgets_positions = function(){
		var positions = Array();
		var sort_keys = Array();
		
		for(var id in _self.containers_assoc){
			positions[id] = {};
			sort_keys[id] = new Array();
		}
		for(var i in _self.widgets){
			var widget = _self.widgets[i];
			if(!widget.isActive){
				continue;
			}
			
			widget.calculate_position();
			positions[widget.container.id][widget.position] = widget.code;
			sort_keys[widget.container.id].push(widget.position);
		}

		//sort the positions array by key
		for(var i in positions){
			var temp_pos = positions[i];
			positions[i] = {};
			sort_keys[i].sort();
			
			for(var j in sort_keys[i]){
				positions[i][sort_keys[i][j]] = temp_pos[sort_keys[i][j]];
			}
			
		}
		
		return positions;
	}
	
	/**
	 * collapses all widgets
	 */
	this.collapse_all = function(){
		for(var i in _self.widgets){
			var widget = _self.widgets[i];
			if(!widget.isActive){
				continue;
			}
			
			widget.collapse();
		}
	}
	
	/**
	 * expands all widgets
	 */
	this.expand_all = function(){
		for(var i in _self.widgets){
			var widget = _self.widgets[i];
			if(!widget.isActive){
				continue;
			}
			
			widget.expand();
		}
	}
	
	/**
	 * adds an error
	 */
	_self.add_error = function(error_message){
		_self.error += (_self.error?'\n':'')+error_message;
	}
	
	/**
	 * adds an warning
	 */
	_self.add_warning = function(warning_message){
		_self.warning += (_self.warning?'\n':'')+warning_message;
	}

	/**
	 * reloads the container according to the new class
	 */
	 
	this.reload_containers = function(){
		_self.containers = Array();
		
		var temp = $('.'+_self.container_class);

		for(var i=0; i<temp.length; i++){
			var temp_container = temp.get(i);
			_self.containers.push(temp_container);
			if(temp_container.id){
				_self.containers_assoc[temp_container.id] = temp_container;
			}
		}
	}
	
	/**
	 * get a vidget by it's wrapper id
	 * 
	 * @param string id
	 * @return widget or false on failure 
	 */
	this.get_widget_by_elem_id = function(id){
		var widget = false;
		
		if(typeof(id)=='string'){
			var matches = id.match(/^widget_(.+)$/)
			
			if(matches && typeof(_self.widgets[matches[1]])=='object'){
				widget = _self.widgets[matches[1]];
			}
		}
		
		return widget;
	}
	
	/**
	 * creates a new widget
	 * 
	 * @param Object parameters = {
	 * 		content:html_content
	 * 		title:string_title
	 * 		code:an_unique_id
	 * 		container:the_element2append2		// optional
	 * 		position:1							// optional
	 * 		hasSettins:false					// optional
	 * 		fixedCell:false						// optional
	 * 		removable:true						// optional
	 * }
	 */
	this.widget = function(parameters){
		this.isActive = true;
		this.isCollapsed = false;
		this.fixedCell = false;
		this.position = false;
		this.container = false;
		this.code = true;
		this.removable = true;
		
		var _self_wid = this;
		if(typeof(parameters)!='object'){
			return;
		}
		
		if(typeof(parameters.content)!='object' && typeof(parameters.content)!='string'){
			_self.add_error('Invalid content');
			return;
		}
		
		if(typeof(parameters.title)!='string'){
			_self.add_error('Invalid title');
			return;
		}
		
		if(typeof(parameters.code)!='string'){
			_self.add_error('Invalid code');
			return;
		}
		
		if(typeof(parameters.removable)=='boolean'){
			this.removable = parameters.removable;
		}
		
		if(typeof(parameters.fixedCell)=='boolean'){
			_self_wid.fixedCell = parameters.fixedCell;
		}
		
		this.code = parameters.code;
		_self.widgets[parameters.code] = this;
		
		this.wraper = document.createElement('div');
		this.wraper.className = 'widget-item-container ui-widget ui-widget-content ui-corner-all';
		this.wraper.id = 'widget_'+parameters.code;
		this.titleBar = document.createElement('div');
		this.titleBar.className = 'windget-title-bar ui-widget-header ui-corner-all';
		this.wraper.appendChild(this.titleBar);
		this.content = document.createElement('div');
		this.wraper.appendChild(this.content);
		
		this.remove = function(){
			_self_wid.isActive = false;
			this.wraper.parentNode.removeChild(this.wraper);
			
			// widgets positions have been updated
			_self.updated();
		}
		
		/**
		 * collapses the widget
		 */
		this.collapse = function(){
			$(nimibize_btn).toggleClass("ui-icon-minusthick").toggleClass("ui-icon-plusthick");
			nimibize_btn.onclick = _self_wid.expand;
			nimibize_btn.title = 'expand';
			$(_self_wid.content).hide('blind', 500);
			this.isCollapsed = true;
		}
		
		/**
		 * expands the widget
		 */
		this.expand = function(){
			$(nimibize_btn).toggleClass("ui-icon-minusthick").toggleClass("ui-icon-plusthick");
			nimibize_btn.onclick = _self_wid.collapse;
			nimibize_btn.title = 'collapse';
			$(_self_wid.content).show('blind', 500);
			this.isCollapsed = false;
		}
		
		// build the title bar
		var title = document.createElement('span');
		title.innerHTML = parameters.title;
		this.titleBar.appendChild(title);
		
		var btn_plh = document.createElement('div');
		btn_plh.className = 'windget-title-bar-btn-plh';
		this.titleBar.appendChild(btn_plh);
		
		// minimize but
		var nimibize_btn = document.createElement('span');
		nimibize_btn.className = 'ui-icon ui-icon-minusthick';
		nimibize_btn.title = 'collapse';
		nimibize_btn.onclick = this.collapse;
		btn_plh.appendChild(nimibize_btn);
		// settings but
		if(parameters.hasSettings){
			var settings_btn = document.createElement('span');
			settings_btn.className = 'ui-icon ui-icon-gear';
			settings_btn.title = 'settings';
			settings_btn.onclick = function() {
				_self.widget_settings_handler(parameters.code);
			}
			btn_plh.appendChild(settings_btn);
		}
		// close but
		if(this.removable){
			var close_btn = document.createElement('span');
			close_btn.className = 'ui-icon ui-icon-closethick';
			close_btn.title = 'close';
			close_btn.innerHTML = 'close';
			close_btn.onclick = function() {
				_self_wid.remove();
			}
			btn_plh.appendChild(close_btn);
		}
		
		// append the content
		if(typeof(parameters.content)=='string'){
			var temp_content = document.getElementById(parameters.content);
			if(temp_content){// is an element id
				parameters.content = temp_content;
			}
			else{
				this.content.innerHTML = parameters.content;
			}
		}
		if(typeof(parameters.content)=='object'){
			// remove scripts not to be reevaluted on move
			$(parameters.content).find('script').remove();
			
			this.content.appendChild(parameters.content);
		}
		
		// append widget to container
//		if(typeof(parameters.container)=='string' && _self.containers_assoc[parameters.container]){ // container id
		if(typeof(parameters.container)=='string'){ // container id
//			_self.containers_assoc[parameters.container].appendChild(_self_wid.wraper);
			try{
				$("#" + parameters.container).append(_self_wid.wraper); // This code works but I don't know if it's always right
			} catch (e){}
		}
		else if(typeof(parameters.container)=='object'){ // container object
			parameters.container.appendChild(_self_wid.wraper);
		}
		else{ // first container
			_self.containers[0].appendChild(_self_wid.wraper);
		}
		
		/**
		 * sets the new container
		 */
		this.update_container = function(){
			_self_wid.container = _self_wid.wraper.parentNode;
		}
		
		
		/**
		 * sets the position of the widget inside the cell
		 * 
		 * @param int position 1 based
		 */
		this.set_position = function(position){
			_self_wid.update_container();
			
			if(position<=1){
				$(_self_wid.container).prepend(_self_wid.wraper);
			}
			else{
				var children = $(_self_wid.container).children();
				
				if(children.length>position){
					$(children[position-2]).after(_self_wid.wraper);
				}
				else{
					_self_wid.container.appendChild(_self_wid.wraper);
				}
			}
			
			_self_wid.calculate_position();
		}
		
		/**
		 * calculate the position inside the cell
		 */
		this.calculate_position = function(){
			return _self_wid.position = $(_self_wid.wraper).prevAll(_self_wid.wraper.tagName.toString().toLowerCase()).length + 1;
		}
		
		if(typeof(parameters.position)=='number'){
			this.set_position(parameters.position);
		}
		this.update_container();
		this.calculate_position();
		
		// make it dragable
		_self.dragable();
	}
}
