/**
* Esta classe tem como objetivo construir um calendario
* generico para ser usado para controlar eventos
*
* @author Erix Henrique Morato <emorato@unibh.br>
* @param strNome - Nome do Calendario
* @param arrEventos - arrContendo os eventos no formato array[data][indice] = nome do evento
* @bolNavegMeses - Variavel que indica se será criando o metodo de navegacao dos meses
* @since 16/08/2006                                                                                                  
*/

ItemCalendario = function(strNome,strClasseCalendario,arrEventos)
{
	// criando array de eventos
	if(arrEventos==undefined)
	{
		this.arrEventos = new Array();
	}
	else
	{
		this.arrEventos = arrEventos;
	}
	// crinado variavel que verifica se será criado navegacao
	this.bolNavegMeses = true;
	// criando objeto que controla posicionada pelo usuario
	this.objDatePosAtual = new Date();
	
	// data do calendario
	this.bolData = false;
	
	// nome do calendario
	this.strNome = strNome;	
	// classe de estilo do calendario
	this.strClasseCalendario = strClasseCalendario;
	// criando objeto que controla a data corrente
	this.objDateCorrente = new Date();
	// array de meses por extenso
	this.arrMeses=new Array("Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro");
	// div principal onde sera colocado o calendario
	this.divPrincipalCalendario = "";	
	
	//habilitar evento no click
	this.strNomEventoClick = "eventoClick";
	this.bolEventoClick = false;
	this.strDataEventoClick="";
	this.strIdElemento = "";
	
}
/**
* Metodo para disparar evento no click
*
* @author Erix Henrique Morato <emorato@unibh.br>
* @since 15/09/2006
* @access public
*/
ItemCalendario.prototype.setEventoClick = function(bolEventoClick,strNomEventoClick,strData,strIdElemento)
{
	this.bolEventoClick = bolEventoClick;	
	if(strNomEventoClick)
	{		
		this.strNomEventoClick = strNomEventoClick;	
	}
	if(strData)
	{
		this.strDataEventoClick = strData;
	}
	if(strIdElemento)
	{		
		this.strIdElemento = strIdElemento;
	}	
}


/**
* Metodo para retornar o nome do calendario
*
* @author Erix Henrique Morato <emorato@unibh.br>
* @since 21/08/2006
*/
ItemCalendario.prototype.getNome = function()
{
	return this.strNome;
}

/**
* Metodo para adicionar um evento
*
* @author Erix Henrique Morato <emorato@unibh.br>
* @param strData - data do evento no formato dd/mm/yyyy
* @param strEvento = nome do evento
* @since 16/08/2006
*/
ItemCalendario.prototype.adicionaEvento = function(strData,strEvento)
{
	if(this.arrEventos[strData] == undefined)
	{
		this.arrEventos[strData] = new Array();
	}	
	this.arrEventos[strData][this.arrEventos[strData].length] = strEvento;	
	if(this.divPrincipalCalendario!="")
	{		
		this.geraCalendario(this.divPrincipalCalendario);
	}	
}

/**
* Metodo para adicionar um evento
*
* @author Erix Henrique Morato <emorato@unibh.br>
* @param strData - data do evento no formato dd/mm/yyyy
* @param strEvento = nome do evento
* @since 16/08/2006
*/
ItemCalendario.prototype.removeEvento = function(strData,strEvento)
{		
	if(this.arrEventos[strData] == undefined)
	{
		return;
	}
	var arrEvento = new Array();	
	for(var intI=0;intI<this.arrEventos[strData].length;intI++)
	{
		if(this.arrEventos[strData][intI] != strEvento)
		{			
			arrEvento[arrEvento.length] = this.arrEventos[strData][intI];
		}
	}
	if(arrEvento.length==0)
		this.arrEventos[strData] = undefined;
	else
		this.arrEventos[strData] = arrEvento;
	if(this.divPrincipalCalendario!="")	
		this.geraCalendario(this.divPrincipalCalendario);
}

/**
* Metodo para remover todos os eventos
*
* @author Erix Henrique Morato <emorato@unibh.br>
* @param strData - data do evento no formato dd/mm/yyyy
* @param strEvento = nome do evento
* @since 16/08/2006
*/
ItemCalendario.prototype.removeTodosEventos = function()
{		
	this.arrEventos = new Array();
}


/**
* Metodo para retornar as datas que possuem eventos
*
* @author Erix Henrique Morato <emorato@unibh.br>
* @param strData - data do evento no formato dd/mm/yyyy
* @param strEvento = nome do evento
* @since 16/08/2006
*/
ItemCalendario.prototype.getDatasEventos = function()
{
	var arrEventos = new Array();
	for(var strData in this.arrEventos)
	{
		arrEventos[arrEventos.length] = strData;
	}
	return arrEventos;
}

/**
* Metodo para retornar se existe evento na data 
*
* @author Erix Henrique Morato <emorato@unibh.br>
* @param strData - data do evento no formato dd/mm/yyyy
* @param strEvento = nome do evento
* @since 16/08/2006
*/
ItemCalendario.prototype.isEvento = function(strData)
{	
	if(this.arrEventos[strData] == undefined)
	{
		return false;	
	}
	return (this.arrEventos[strData].length > 0)
}

/**
* Metodo para retornar os eventos por data
*
* @author Erix Henrique Morato <emorato@unibh.br>
* @param strData - data do evento no formato dd/mm/yyyy
* @param strEvento = nome do evento
* @since 16/08/2006
*/
ItemCalendario.prototype.getEventosData = function(strData)
{
	if(this.arrEventos[strData] == undefined)
	{
		return new Array();
	}
	return this.arrEventos[strData];
}

/**
* Metodo para obter quantos dias tem um mes
*
* @author Erix Henrique Morato <emorato@unibh.br>
* @param intMes - Mes (de 1 a 12)
* @param intAno - ano
* @since 16/08/2006
*/
ItemCalendario.prototype.obterNumDiasMes = function(intMes,intAno)
{
	  var arrDias = new Array(31,28,31,30,31,30,31,31,30,31,30,31);
	  var intDia = arrDias[intMes-1];
	  if(intAno%4==0 && intMes==2) {
	    intDia = 29;
	  }
	  return intDia;
}

/**
* Metodo para obter o dia de uma data
*
* @author Erix Henrique Morato <emorato@unibh.br>
* @param objDate - objeto contendo a data
* @since 16/08/2006
*/
ItemCalendario.prototype.getDia = function(objDate,bolZeroEsqueda)
{
	var intDia = objDate.getDate();
	var strDia = "";
	if(bolZeroEsqueda)
	{
		if (intDia < 10)
				strDia = "0"+intDia;
			else
				strDia = intDia;
	}
	else strDia = intDia;
	return strDia;
}

/**
* Metodo para obter o mes de uma data
*
* @author Erix Henrique Morato <emorato@unibh.br>
* @param objDate - objeto contendo a data
* @since 16/08/2006
*/
ItemCalendario.prototype.getMes = function(objDate,bolZeroEsqueda)
{
	var intMes = (objDate.getMonth()+1);
	var strMes = "";
	if(bolZeroEsqueda)
	{
		if (intMes < 10)
				strMes = "0"+intMes;
			else
				strMes = intMes;
	}
	else strMes = intMes;
	return strMes;
}

/**
* Metodo para obter o mes em extenso de uma data
*
* @author Erix Henrique Morato <emorato@unibh.br>
* @param objDate - objeto contendo a data
* @since 16/08/2006
*/
ItemCalendario.prototype.getMesExtenso = function(objDate)
{
	return this.arrMeses[objDate.getMonth()];
}



/**
* Metodo para obter o ano de uma data
*
* @author Erix Henrique Morato <emorato@unibh.br>
* @param objDate - objeto contendo a data
* @since 16/08/2006
*/
ItemCalendario.prototype.getAno = function(objDate)
{
	return objDate.getFullYear();
}

/**
* Metodo para converter uma data para string
*
* @author Erix Henrique Morato <emorato@unibh.br>
* @param objDate - objeto contendo a data
* @since 16/08/2006
*/
ItemCalendario.prototype.dateToStr = function(objDate)
{
	return (this.getDia(objDate,true) + '/'+ this.getMes(objDate,true) +'/'+this.getAno(objDate));
}

/**
* Metodo para converter um string para data
*
* @author Erix Henrique Morato <emorato@unibh.br>
* @param objDate - objeto contendo a data
* @since 16/08/2006
*/
ItemCalendario.prototype.strToDate = function(strData)
{
	var objDate = new Date();
	var arrData = strData.split('/');
	var strMes = arrData[1];
	strMes0 = strMes.substring(0,1);
	strMes1 = strMes.substring(1);	
	if(strMes0=='0')
	{
		strMes = strMes1;
	}
	objDate.setFullYear(arrData[2],parseInt(strMes)-1,arrData[0]);
	objDate.setHours(0,0,0,0);
	return objDate;
}
/*
*/
/**
* Metodo para retornar o primeiro dia do mes que está no determinado dia da semana
* 
* @author Daniel Hasan Dalip <dhasan@unibh.br>
* @param Primeiro dia do mes que está no determinado dia da semana
* @since 18/02/2008
*/
ItemCalendario.prototype.getPrimeiroDiaMes = function(objDate,intDiaSemana)
{
	var intDiaSemanaDiaUm = gObjCalendario.getDiaSemana(objDate);
	var intPrimeiroDiaMes = 1+(intDiaSemana-intDiaSemanaDiaUm);
	if(intPrimeiroDiaMes<=0)
	{
		intPrimeiroDiaMes+=7;
	}
	return intPrimeiroDiaMes;
}
/**
* Metodo para verificar se o dia é util
*
* @author Erix Henrique Morato <emorato@unibh.br>
* @param intDia - dia a ser verificado
* @since 16/08/2006
*/
ItemCalendario.prototype.isDiaUtil = function(objDate)
{
	if (!objDate)
	{
		return !(this.objDatePosAtual.getDay()==6 || this.objDatePosAtual.getDay()==0);
	}
	else
	{
		return !(objDate.getDay()==6 || objDate.getDay()==0);
	}
}

/**
* Metodo para retornar o numero da semana no ano
* adaptado de:  http://www.meanfreepath.com/support/getting_iso_week.html
* @author Daniel Hasan Dalip <hdalip@gmail.com>
* @param objDate - objeto contendo a data
* @since 14/03/2008
*/
ItemCalendario.prototype.getNumSemana = function(objDate)
{
	/*getWeek() was developed by Nick Baicoianu at MeanFreePath: http://www.meanfreepath.com */
	
	dowOffset = 0; //default dowOffset to zero
	var newYear = new Date(objDate.getFullYear(),0,1);
	var day = newYear.getDay() - dowOffset; //the day of week the year begins on
	day = (day >= 0 ? day : day + 7);
	var daynum = Math.floor((objDate.getTime() - newYear.getTime() -
				(objDate.getTimezoneOffset()-newYear.getTimezoneOffset())*60000)/86400000) + 1;
	var weeknum;
	//if the year starts before the middle of a week
	if(day < 4) 
	{
		weeknum = Math.floor((daynum+day-1)/7) + 1;
		if(weeknum > 52) 
		{
			nYear = new Date(objDate.getFullYear() + 1,0,1);
			nday = nYear.getDay() - dowOffset;
			nday = nday >= 0 ? nday : nday + 7;
			/*if the next year starts before the middle of
			the week, it is week #1 of that year*/
			weeknum = nday < 4 ? 1 : 53;
		}
	}
	else 
	{
		weeknum = Math.floor((daynum+day-1)/7);
	}
	return weeknum;

}

/**
* Metodo para verificar se o dia é util
*
* @author Erix Henrique Morato <emorato@unibh.br>
* @param intDia - dia a ser verificado
* @since 16/08/2006
*/
ItemCalendario.prototype.getDiaSemana = function(objDate)
{
	return objDate.getDay();	
}
/**
* Metodo para adicionar dias a uma data 
*
* @author Daniel Hasan Dalip <hdalip@gmail.com>
* @param objDate - objeto contendo a data
* @since 24/03/2008
*/
ItemCalendario.prototype.adicionaDiaData = function(objDate,intQtdDias)
{
	var objDataAdicionada = this.strToDate(this.dateToStr(objDate));
	
	objDataAdicionada.setTime(objDate.getTime()+
				(intQtdDias
				  *24//horas
				  *60//minutos
				  *60//segundos
				  *1000//milissegundos
				)
			);
	return objDataAdicionada;
}
/**
* Metodo para verificar se é o dia corrente
*
* @author Erix Henrique Morato <emorato@unibh.br>
* @param intDia - dia a ser verificado
* @since 16/08/2006
*/
ItemCalendario.prototype.isDataCorrente = function()
{
	return this.dateToStr(this.objDatePosAtual)==this.dateToStr(this.objDateCorrente);	
}

/**
* Metodo para gerar o calendario do proximo mes
*
* @author Erix Henrique Morato <emorato@unibh.br>
* @param intDia - dia a ser verificado
* @since 16/08/2006
*/
ItemCalendario.prototype.proximoMes = function(intDia)
{
	var intAno = this.getAno(this.objDatePosAtual);
	var intMes = parseInt(this.getMes(this.objDatePosAtual))+1;
	// verificando se houve mudança de ano
	if (intMes > 12)
	{
			intAno = intAno+1;
			intMes = 1;
	}
	this.objDatePosAtual.setFullYear(intAno, intMes, 0);
	this.geraCalendario(this.divPrincipalCalendario);
}

/**
* Metodo para gerar o calendario do mes anterior
*
* @author Erix Henrique Morato <emorato@unibh.br>
* @param intDia - dia a ser verificado
* @since 16/08/2006
*/
ItemCalendario.prototype.mesAnterior = function(intDia)
{
	var intAno = this.getAno(this.objDatePosAtual);	
	var intMes = parseInt(this.getMes(this.objDatePosAtual)) - 1;	
	// verificando se houve mudança de ano
	if (intMes < 0)
	{
			intAno = intAno - 1;
			intMes = 11;
	}
	this.objDatePosAtual.setFullYear(intAno, intMes, 0);
	this.geraCalendario(this.divPrincipalCalendario);				
}


/**
* Metodo gerar o cabecalho
*
* @author Erix Henrique Morato <emorato@unibh.br>
* @param objDivCalendario - Objeto calendario
* @since 16/08/2006
*/
ItemCalendario.prototype.geraCabecalho = function(objDivCalendario)
{
		var objCabecalho = document.createElement('div');
		// criando objeto do calendario
		var objCalendario = this;
		objCabecalho.id = this.strNome+"_cabecalho";
		// classe de estilo do cabecalho
		objCabecalho.className = 'cabecalho';
		
		var objConteinerCab = document.createElement('div');
		objConteinerCab.id = this.strNome+"_subCabecalho"
		objConteinerCab.className = 'subCabecalho';
		
		// meses
		var objTextMes = document.createElement('div');
		objTextMes.id = this.strNome+'_textoMes';
		objTextMes.className = 'cabecalhoTexto';		
		objTextMes.innerHTML = this.arrMeses[(parseInt(this.getMes(this.objDatePosAtual))-1)]+"/"+this.getAno(this.objDatePosAtual);
			
		// criando links de navegacao		
		if(this.bolNavegMeses)
		{
			// anterior
			var objNavegAnterior = document.createElement('a');
			objNavegAnterior.id = this.strNome+'_navegAnterior';
			objNavegAnterior.className = 'navegAnterior';
			objNavegAnterior.onclick = function(){
				objCalendario.mesAnterior();
			}
			
			// proximo
			var objNavegProximo = document.createElement('a');
			objNavegProximo.id = this.strNome+'_navegProximo';
			objNavegProximo.className = 'navegProximo';
			objNavegProximo.onclick = function(){
				objCalendario.proximoMes();
			}
									
			objConteinerCab.appendChild(objNavegAnterior);
			objConteinerCab.appendChild(objTextMes);
			objConteinerCab.appendChild(objNavegProximo);
		}
		else
		{
			objTextMes.style.width =  "100%";
			objConteinerCab.appendChild(objTextMes);
		}
		// gerando cabecalho
		objCabecalho.appendChild(objConteinerCab);
		
		// adicionando cabecalho no conteiner do calendario
		objDivCalendario.appendChild(objCabecalho);		
}

/**
* Metodo gerar a legenda dos dias da semena
*
* @author Erix Henrique Morato <emorato@unibh.br>
* @param objDivCalendario - Objeto calendario
* @since 16/08/2006
*/
ItemCalendario.prototype.geraLegendaSemana = function(objDivCalendario,strData)
{
		var arrLegSemana = new Array("D","S","T","Q","Q","S","S");
		for(var intI=0;intI<arrLegSemana.length;intI++)
		{
			var objDia = document.createElement('div');
			objDia.id = this.strNome + "_diaLegenda"+intI;
			objDia.className = 'dia';
			objDia.innerHTML = arrLegSemana[intI];
			objDivCalendario.appendChild(objDia);
			
			//funcao callback padrao da legenda
			objDia.strNome = this.strNome;
			objDia.intI = intI;
			objDia.onclick = function(event)
			{						
				try
				{
					var strNomFuncao = "func"+this.strNome+"_Legenda_onclick(this,event,this.intI,strData);";
					//alert('vai funcao: '+strNomFuncao);
					eval(strNomFuncao);
				}
				catch(objErro){
					
				}
			}
		}
}


/**
* Metodo gerar o div do dia do calendario
*
* Para cada dia com evento desenhado é chamada uma função de callback seguindo este padrão:
* func"+nome do calendario+"_"+nome do evento+"(objDiv,'"+strData+"');";
*
* Para cada dia com evento desenhado é chamada uma função de callback seguindo este padrão:
* func"+nome do calendario+"_Dia_(objDiv,'"+strData+"');";
*
* @author Erix Henrique Morato <emorato@unibh.br>
* @param objDivCalendario - Objeto calendario
* @since 16/08/2006
*/
ItemCalendario.prototype.criaDivConteudo = function(intPosCorrente,intDiaSemana,intMaxDiaMes)
{
	// iniciando variaveis		
	var strData = this.dateToStr(this.objDatePosAtual);
	var arrEventoData = this.arrEventos[strData];
	
	// criando div referente ao dia
	var objDiv = document.createElement('div');
	if((intPosCorrente<intDiaSemana) || ((intPosCorrente)>=(intMaxDiaMes+intDiaSemana)))
	{
		objDiv.className = 'outroMes';
		objDiv.innerHTML = "";
		if (intPosCorrente>intMaxDiaMes)
		{
			objDiv.style.display = 'none';
		}
	}
	else
	{
		objDiv.id = this.strNome+'_diaConteudo'+strData;
		
		var intDia = parseInt(this.getDia(this.objDatePosAtual,false));		
		objDiv.innerHTML = intDia;
		if(this.isDataCorrente())
		{
			objDiv.className = 'dataCorrente';
		}
		else if(this.isDiaUtil())
		{
			objDiv.className = 'diaUtil';
		}
		else
		{
			objDiv.className = 'fimSemana';
		}
		if(arrEventoData !=undefined)
		{						
			objDiv.className = 'evento';
			for(var intJ=0; intJ<arrEventoData.length;intJ++)
			{
				try
				{
					var strNomFuncao = "func"+this.strNome+"_"+arrEventoData[intJ]+"(objDiv,'"+strData+"');";
					
					//alert(strNomFuncao);
					eval(strNomFuncao);
				}
				catch(objErro){
					
				}
			}
		}
		else
		{
			try
			{
				var strNomFuncao = "func"+this.strNome+"_Dia_(objDiv,'"+strData+"');";
				
				//alert(strNomFuncao);
				eval(strNomFuncao);
			}
			catch(objErro){
				
			}	
		}
		
		//funcao callback padrao do dia
		objDiv.strIdElemento = this.strIdElemento;
		objDiv.strNome = this.strNome;
		objDiv.arrEventoData = arrEventoData;
		
		objDiv.onclick = function(event)
		{						
			try
			{
				var strNomFuncao = "func"+this.strNome+"_Dia_onclick(this,event,'"+strData+"',this.arrEventoData);";
				//alert('vai funcao: '+strNomFuncao);				
				eval(strNomFuncao);
			}
			catch(objErro){
				
			}
		}
		
		if(this.bolEventoClick)
		{
			objDiv.strNomEventoClick = this.strNomEventoClick;
			if(this.strDataEventoClick!="")
			{				
				if(this.strDataEventoClick==strData)
				{
					objDiv.bolEvento = this.isEvento(strData);
					objDiv.strIdElemento = this.strIdElemento;
					objDiv.onclick = function(event)
					{						
						var strNomFuncao = this.strNomEventoClick+"('"+strData+"','"+this.strIdElemento+"',objDiv,event);";
						eval(strNomFuncao);						
					}
					objDiv.onmouseover = function()
					{
						this.className = 'evento';
					}
					
					objDiv.onmouseout = function()
					{
						if(!this.bolEvento)
							this.className = 'diaUtil';
						else
						{
							this.className = 'evento';
						}
					}
				}
			}
			else
			{				
				objDiv.strIdElemento = this.strIdElemento;
				objDiv.bolEvento = this.isEvento(strData)				
				objDiv.onclick = function(event)
				{
					var strNomFuncao = this.strNomEventoClick+"('"+strData+"','"+this.strIdElemento+"',objDiv,event);";					
					eval(strNomFuncao);						
				}			
				objDiv.onmouseover = function()
				{
					this.className = 'evento';
				}				
				
				objDiv.onmouseout = function()
				{
					if(!this.bolEvento)
						this.className = 'diaUtil';
					else
					{
						this.className = 'evento';
					}
				}
			}
		}
		if((intDia+1) <= intMaxDiaMes)
		{
			//duas vezes, pois para o dia 12 de outubro de 2008 existe um bug caotico que nao permite a geracao do dia na primeira tentativa
			this.objDatePosAtual.setDate(intDia+1);
			this.objDatePosAtual.setDate(intDia+1);
		}
	}
	return objDiv;
}

/**
* Metodo gerar o conteudo do calendario
*
* @author Erix Henrique Morato <emorato@unibh.br>
* @param objDivCalendario - Objeto calendario
* @since 16/08/2006
*/
ItemCalendario.prototype.geraConteudo = function(objDivCalendario)
{	
	// iniciando variaveis
	this.objDatePosAtual.setDate(1);
	var intDia = parseInt(this.getDia(this.objDatePosAtual,false));
	var intMes = parseInt(this.getMes(this.objDatePosAtual,false));	
	var intAno = this.getAno(this.objDatePosAtual);
	var intMaxDiaMes = this.obterNumDiasMes(intMes,intAno);	
	var intDiaSemana = this.objDatePosAtual.getDay();		
	for(var intI=0;intI<42;intI++)
	{				
		var objDiv = this.criaDivConteudo(intI,intDiaSemana,intMaxDiaMes);		
		objDivCalendario.appendChild(objDiv);
	}	
}

/**
* Metodo gerar um calendario
*
* @author Erix Henrique Morato <emorato@unibh.br>
* @param strDivPrincipal - Div que esta sendo gerado o calendario
* @param strData - Data que será gerado o calendario
* @since 16/08/2006
*/
ItemCalendario.prototype.geraCalendario = function(strDivCalendario,strData,bolNavegacao)
{
		this.divPrincipalCalendario = strDivCalendario;			
		if(!this.bolData)
		{
			if(strData == undefined || strData== "")
			{
				// crinado variavel que verifica se será criado navegacao
				this.bolNavegMeses = bolNavegacao==undefined?true:bolNavegacao;
				// criando objeto que controla posicionada pelo usuario
				this.objDatePosAtual = new Date();
			}
			else
			{
				// crinado variavel que verifica se será criado navegacao
				this.bolNavegMeses = bolNavegacao==undefined?false:bolNavegacao;
				// criando objeto que controla posicionada pelo usuario
				this.objDatePosAtual = this.strToDate(strData);
			}
			
			//modificacao feita pro alex - nao entendi o motivo desse true
			this.bolData = true;
		}
		
		// criando calendario	
		var objDivCalendario = document.createElement('div');
		//alert(this.strNome);
		objDivCalendario.id = this.strNome;
		objDivCalendario.className = this.strClasseCalendario;
		
		// criando cabecalho
		this.geraCabecalho(objDivCalendario);
		
		// criando legenda da semana
		this.geraLegendaSemana(objDivCalendario,strData);
		
		// criando conteudo
		this.geraConteudo(objDivCalendario);
		
		// adicionando calendario no tela
		var objDivPrincipal = document.getElementById(this.divPrincipalCalendario);		
		//alert(this.divPrincipalCalendario);
		objDivPrincipal.innerHTML = "";
		//alert(objDivCalendario.innerHTML);
		objDivPrincipal.appendChild(objDivCalendario);		
}
