//CONSTANTS
//queue execution status: 0-empty, 1-ready, 2-busy
//queue operations status: 0-none, 1-busy
//action status: 0-pending, 1-active
//limit_type: restrict, replace, remove

//optiune de mesaj in notice

var famundoActions = {
	queues : new Object(),
	
	add: function (action_obj, queue_name)
		{
		var q = this._createQueue(queue_name);
		this._addAction(q.name, action_obj);

		if (this.queues[q.name]['status']==0)
			{
			this.queues[q.name]['status'] = 1;
			this._exec(q.name);
			}
		},
	
	_createQueue: function (queue_name)
		{
		queue_name = queue_name || 'famundo';
		if (!this.queues[queue_name])
			{
			this.queues[queue_name] = new Object();
			this.queues[queue_name]['name'] = queue_name;
			this.queues[queue_name]['actions'] = new Array();
			this.queues[queue_name]['status'] = 0;
			this.queues[queue_name]['op_status'] = 0;
			}
		return this.queues[queue_name];
		},
	
	_addAction: function(queue_name, action_obj)
		{
		//change queue operation status to busy.no other operation on queue is allowed until this is finished
		this.queues[queue_name]['op_status'] = 1;
		action_obj['action_type'] = action_obj['action_type'] || 'secvential';
		//set action status to pending
		action_obj['status'] = 0;
		switch (action_obj['action_type'])
			{
			case 'custom':
				switch (action_obj['custom_type'])
					{
					case 'display_calendar':
						this._addDisplayCalendar(queue_name, action_obj);
						break;
					case 'display_user':
						this._addDisplayUser(queue_name, action_obj);
						break;
					case 'calendar_next_month':
						this._addNavigationCalendar(queue_name, action_obj, 'calendar_next_month');
						break;
					case 'calendar_previous_month':
						this._addNavigationCalendar(queue_name, action_obj, 'calendar_previous_month');
						break;
					case 'calendar_drop_date':
						this._addCalendarDropDate(queue_name, action_obj);
						break;
					}
				break;
			
			default:
				if (!action_obj['limit'])
					{
					this.queues[queue_name].actions.push(action_obj);
					}
				else
					{
					if (!action_obj['action_id'])
						alert("DEV ERROR!You must set an action id!");
					switch (action_obj['limit_type'])
						{
						case 'restrict' :
							this._addActionLimitRestrict(queue_name, action_obj);
							break;
						case 'replace' :
							this._addActionLimitReplace(queue_name, action_obj);
							break;
						case 'remove' :
							this._addActionLimitRemove(queue_name, action_obj);
							break;
						default :
							this._addActionLimitRestrict(queue_name, action_obj);
							break;
						}
					}
				break;
			}
	  	this.queues[queue_name]['op_status'] = 0;	
		},
			
	_exec: function(queue_name)
		{
		if (this.queues[queue_name]['status'] == 1) //queue ready (not busy or empty)
			{
			//set queue to busy
			this.queues[queue_name]['status'] = 2;
			//mark action as active
			//this.queues[queue_name].actions[0]['status'] = 1;
			var action_obj = this.queues[queue_name].actions[0];
			var me = this;
			switch (action_obj['action_type'])
				{
				case 'secvential':
					setTimeout(function() {						
						me.queues[queue_name].actions[0]['status'] = 1;
						var action_obj = me.queues[queue_name].actions[0];
						action_obj.func();
						me.queues[queue_name].actions.shift();
						me._execNext(queue_name);
						}, action_obj['delay']||0);
					
					break;
					
				case 'ajax':
					setTimeout(function() 
						{
						me.queues[queue_name].actions[0]['status'] = 1;
						var action_obj = me.queues[queue_name].actions[0];
						var ajx = action_obj.func();
						var i = setInterval(function() 
							{ 
							//if(me.queues[queue_name]['op_status']==0 && ajx.transport.readyState==4) 
							if(me.queues[queue_name]['op_status']==0 && Ajax.activeRequestCount==0)
								{ 
								clearInterval(i);
								me.queues[queue_name].actions.shift();
								me._execNext(queue_name);
								}  
							}, 100);
						}, action_obj['delay']||0);
					break;
				
				case 'parallel':
					this.queues[queue_name].actions[0]['status'] = 1;
					action_obj.func();
					var me = this;
					setTimeout(function() {
						me.queues[queue_name].actions.shift();
						me._execNext(queue_name);
					},action_obj['duration']||1000);
					break; 
				
				}
			}
		},
		
	_execNext: function(queue_name)
		{
		if (this.queues[queue_name].actions.length>0)
			{
			this.queues[queue_name]['status'] = 1;
			this._exec(queue_name);
			}
		else
			{
			this.queues[queue_name]['status'] = 0;
			}
		},
		
	_addActionLimitRestrict: function(queue_name, action_obj)
		{
		if (this._checkLimit(queue_name, action_obj))
			this.queues[queue_name].actions.push(action_obj);
		},

	_addActionLimitReplace: function(queue_name, action_obj)
		{
		var actions = this.queues[queue_name].actions;
		
		if (actions.length == 0)
			{
			//console.log('empty queue');
			this.queues[queue_name].actions.push(action_obj);
			return ;
			}
		var count = 0;
		var last = 0;
		
		for(var i=0;i<actions.length;i++)
			{
			if (actions[i]['action_id'] && actions[i]['action_id']==action_obj['action_id'])
				{
				count++;
				var last = i;
				}
			}
		if (action_obj['limit'] > count)
			{
			this.queues[queue_name].actions.push(action_obj);
			}
		else if (this.queues[queue_name].actions[last].status==0)
			{
			this.queues[queue_name].actions[last] = action_obj;
			}
		},

	_addActionLimitRemove: function(queue_name, action_obj)
		{
		var actions = this.queues[queue_name].actions;
		if (actions.length == 0)
			{
			//console.log('empty queue');
			this.queues[queue_name].actions.push(action_obj);
			return ;
			}
		var count = 0;
		var last = 0;
		
		for(var i=0;i<actions.length;i++)
			{
			if (actions[i]['action_id'] && actions[i]['action_id']==action_obj['action_id'])
				{
				count++;
				var last = i;
				}
			}
		
		if (action_obj['limit']>count)
			{
			this.queues[queue_name].actions.push(action_obj);
			}
		else if (this.queues[queue_name].actions[last].status==0)
			{
			this.queues[queue_name].actions.splice(last,1);
			this.queues[queue_name].actions.push(action_obj);
			}
		},
	
	_checkLimit: function (queue_name, action_obj)
		{
		if (!action_obj['limit'])
			return true;
		action_obj['limit_type'] = action_obj['limit_type'] || 'restrict';
		var count = 0;
		var actions = this.queues[queue_name].actions;
		for(var i=0;i<actions.length;i++)
			{
			if (actions[i]['action_id'] && actions[i]['action_id']==action_obj['action_id'])
				{
				count++;
				}
			}
		return action_obj['limit']>count;
		},

//******** CUSTOM ACTIONS ********

	//only one action of this type('display_calendar'), with status 0(pending), must be in queue.
	//if more 'display_calendar' actions needed, the attributes checked_ids,unchecked_ids are updated. 
	//when action is exec, a single call is made with the params in url like: 
	// ?selected_calendar_checked=12_13_14&selected_calendar_unchecked=1_2_3
	_addDisplayCalendar: function(queue_name, action_obj)
		{

		if (!this._checkLimit(queue_name, action_obj))
			return false;
			
		var actions = this.queues[queue_name].actions;
		var vb = false; 
		var me = this;
		for (var i=0;i<actions.length;i++)
			{
			if (actions[i]['custom_type'] && actions[i]['custom_type']=='display_calendar' && actions[i]['status']==0)
				{
				//action_obj['func'][1] = checked | unchecked
				for (var j=0;j<action_obj['func'].length;j++)
					actions[i][action_obj['func'][j][1]+'_ids'].push(action_obj['func'][j][0]);

				var url = this.getDisplayCalendarUrl(actions[i]['checked_ids'].unique(),actions[i]['unchecked_ids'].unique());
				//console.log(url);
				actions[i]['func'] = function() { return new Ajax.Request(url,{asynchronous:true, method: 'get'});}
				vb = true;
				}
			}
		
		if (!vb)
			{
			action_obj['checked_ids'] = new Array();
			action_obj['unchecked_ids'] = new Array();

			for (var j=0;j<action_obj['func'].length;j++)
				action_obj[action_obj['func'][j][1]+'_ids'].push(action_obj['func'][j][0]);
        
			var url = this.getDisplayCalendarUrl(action_obj['checked_ids'].unique(), action_obj['unchecked_ids'].unique());
			action_obj['func'] = function() { return new Ajax.Request(url,{asynchronous:true, method: 'get'});}
			
			action_obj['action_type'] = 'ajax';
			this.queues[queue_name].actions.push(action_obj);
			}	
		},

	//checked_ids,unchecked_ids: arrays of calendars id
	getDisplayCalendarUrl: function (checked_ids,unchecked_ids)
		{
		separator = '|';
		var params = new Array();
		var str = famundoCalendarUrl.get_refresh_url + '?';
		if (checked_ids && checked_ids.length>0)
			params.push('selected_calendar_checked='+checked_ids.join(separator))
		if (unchecked_ids && unchecked_ids.length>0)
			params.push('selected_calendar_unchecked='+unchecked_ids.join(separator));
		return str+params.join('&') ;
		},

	
	_addDisplayUser: function(queue_name, action_obj)
		{

		if (!this._checkLimit(queue_name, action_obj))
			return false;
			
		var actions = this.queues[queue_name].actions;
		var vb = false; 
		var me = this;
		for (var i=0;i<actions.length;i++)
			{
			if (actions[i]['custom_type'] && actions[i]['custom_type']=='display_user' && actions[i]['status']==0)
				{
				for (var j=0;j<action_obj['func'].length;j++)
					actions[i][action_obj['func'][j][1]+'_ids'].push(action_obj['func'][j][0]);

				var url = this.getDisplayUserUrl(actions[i]['checked_ids'].unique(),actions[i]['unchecked_ids'].unique());
				
				actions[i]['func'] = function() { return new Ajax.Request(url,{asynchronous:true, method: 'get'});}
				vb = true;
				}
			}
		
		if (!vb)
			{
			action_obj['checked_ids'] = new Array();
			action_obj['unchecked_ids'] = new Array();

			for (var j=0;j<action_obj['func'].length;j++)
				action_obj[action_obj['func'][j][1]+'_ids'].push(action_obj['func'][j][0]);
			var url = this.getDisplayUserUrl(action_obj['checked_ids'].unique(), action_obj['unchecked_ids'].unique());
     
			action_obj['func'] = function() { return new Ajax.Request(url,{asynchronous:true, method: 'get'});}
			
			action_obj['action_type'] = 'ajax';
			this.queues[queue_name].actions.push(action_obj);
			}	
		},

	//checked_ids,unchecked_ids: arrays of calendars id
	getDisplayUserUrl: function (checked_ids,unchecked_ids)
		{
		separator = '|';
		var params = new Array();
		var str = famundoCalendarUrl.get_refresh_url + '?';
		if (checked_ids && checked_ids.length>0)
			params.push('selected_user_checked='+checked_ids.join(separator))
		if (unchecked_ids && unchecked_ids.length>0)
			params.push('selected_user_unchecked='+unchecked_ids.join(separator));
		return str+params.join('&') ;
		},
	//navigation between days,weeks and months in calendar section
	_addNavigationCalendar: function(queue_name, action_obj, navigation_type)
		{
		var actions = this.queues[queue_name].actions;
		var vb = false;
		var me = this; 
		for (var i=0;i<actions.length;i++)
			{
			if (actions[i]['custom_type'] && actions[i]['custom_type']==navigation_type && actions[i]['status']==0)
				{
				actions[i]['count']+=1;
				var url = this._getNavigationCalendarUrl(actions[i]);
				actions[i]['func'] = function() { 
					return new Ajax.Request(url ,{asynchronous:true, method: 'get'});
				}
				vb = true;
				}
			}
		
		if (!vb)
			{
			action_obj['count'] = 1;
			action_obj['func'] = function() {
				return new Ajax.Request(me._getNavigationCalendarUrl(action_obj) ,{asynchronous:true, method: 'get'});
			};
			action_obj['action_type'] = 'ajax';
			this.queues[queue_name].actions.push(action_obj);
			}	

		},
	
	_getNavigationCalendarUrl: function(action_obj)
		{
		var param = '';
		if (action_obj['count']>1)
			{
			param = (action_obj['custom_type']=='calendar_next_month') ? 'count='+action_obj['count'] : 'count=-'+action_obj['count'];
			}
		if (action_obj['current_date'])
			{
			if (param != '')
				param = '&'+param;
			return famundoCalendarUrl.get_refresh_url+'?current_date='+action_obj['current_date']+param;	
			}
		else
			{
			if (action_obj['custom_type']=='calendar_next_month')
				{
				return famundoCalendarUrl.get_go_next_url+'?'+param;	
				}
			else
				{
				return famundoCalendarUrl.get_go_prev_url+'?'+param;	
				}			
			}
		},

	_addCalendarDropDate: function(queue_name, action_obj)
		{
		var actions = this.queues[queue_name].actions;
		var vb = false;
		var me = this; 
		for (var i=0;i<actions.length;i++)
			{
			if (actions[i]['custom_type'] && actions[i]['custom_type']=='calendar_drop_date')
				{
				if (actions[i]['status']==0)
					{
					vb = true;
					if (actions[i]['action_id']!=action_obj['action_id'])
						{
						action_obj['action_type'] = 'ajax';
						this.queues[queue_name].actions[i] = action_obj;
						}
					else
						break; 
					}
				else
					{
					if (actions[i]['action_id']==action_obj['action_id'])
						vb = true;
					}
				}
			}
		
		if (!vb)
			{
			action_obj['action_type'] = 'ajax';
			this.queues[queue_name].actions.push(action_obj);
			}	

		}
	

}