function getDateKey(date)
{
	if (typeof date == 'string')  return date.substring(0,8);
	var year = date.getFullYear();
	var month = date.getMonth()+1;
	var day = date.getDate();
	return '' + year + ((month<10)?'0':'')+month + ((day<10)?'0':'')+day;
}

/* ZDate */
function ZDate_addDays(ndays)
{
	if ( !this.date )  this.date = new Date(this.year, this.month-1, this.day, this.hour, this.minute, this.second);
	var new_date = new Date(this.date.getTime()+ndays*(24*60*60*1000));
	var timezone_minute_difference = new_date.getTimezoneOffset() - this.date.getTimezoneOffset();
	if ( timezone_minute_difference )  new_date.setTime(new_date.getTime()+(timezone_minute_difference*60*1000));
	return new ZDate(new_date);
}
function ZDate_getYMD()
{
	var year = this.year;
	var month = this.month;
	var day = this.day;
	return '' + year + month + day;
}
function ZDate_getAnchor()
{
	var year = this.year;
	var month = this.month;
	var day = this.day;
	return '' + year + '-' + month + '-' + day;
}
function ZDate(zdate)
{
	this.addDays = ZDate_addDays;
	this.getYMD = ZDate_getYMD;
	this.getAnchor = ZDate_getAnchor;

	if (typeof zdate == 'string') {
		this.string = zdate;
		this.year = zdate.substring(0,4);
		this.month = zdate.substring(5,7);
		this.day = zdate.substring(8,10);
		if ( zdate.substring(10,11) != 'T' )  return;
		this.hour = zdate.substring(11,13);
		this.minute = zdate.substring(14,16);
		this.second = zdate.substring(17,19);
		this.timezone = zdate.substring(19,25);
	} else {
		this.year = zdate.getFullYear();
		this.month = (((zdate.getMonth()+1)<10)?'0':'')+(zdate.getMonth()+1);
		this.day = ((zdate.getDate()<10)?'0':'')+zdate.getDate();
		this.hour = zdate.getHours();
		this.minute = zdate.getMinutes();
		this.second = zdate.getSeconds();
//		this.timezone = zdate.getTimezone();
	}
	this.date = new Date(this.year, this.month-1, this.day, this.hour, this.minute, this.second);
}

/* Event */
function Event(date_begin, date_end, description, event_key, format_date_type, local, idioma, link, link_vcal)
{
	this.date_begin = date_begin;
	this.date_end = date_end;
	this.description = description;
	this.event_key = event_key;
	this.format_date_type = format_date_type;
	this.local = local;
	this.idioma = idioma;
	this.link = link;
	this.eh_futuro = event_eh_futuro;
	this.less = event_less;
	this.link_vcal = link_vcal;
}
function event_eh_futuro() {
 	
	var agora = new Date();
	
	if (agora > this.date_end.date) { // jah acabou o evento
		return false;
	} else {
		return true;
	}
}

function event_less (e1, e2) {
	return e1.date_begin.date < e2.date_begin.date;
}

/* EventDate */
function EventDate_add(date_begin, date_end, description, event_key, format_date_type, local, idioma, link, link_vcal)
{
	this.events[this.events.length] = new Event(date_begin, date_end, description, event_key, format_date_type, local, idioma, link, link_vcal);
}
function EventDate_get(number)
{
	return this.events[number];
}
function EventDate_count()
{
	return this.events.length;
}
function EventDate()
{
	this.events = new Array();
	this.add = EventDate_add;
	this.get = EventDate_get;
	this.count = EventDate_count;
}

/* Events */
function Events_addEvent(date_begin, date_end, description, event_key, format_date_type, local, idioma, link, link_vcal)
{
	// acrescenta evento em todas as datas entre date_begin e date_end
	for (var date = date_begin; date.getYMD() <= date_end.getYMD(); date = date.addDays(1)) {
		var date_key = date.getYMD();
		if (! this.dates[date_key])  this.dates[date_key] = new EventDate();
		this.dates[date_key].add(date_begin, date_end, description, event_key, format_date_type, local, idioma, link, link_vcal);
	}

	// crio um evento, coloco no array de eventos, ordenado 
	var e = new Event(date_begin, date_end, description, event_key, format_date_type, local, idioma, link, link_vcal);
	insere_ordenado_no_array(e, this.events, 0);

}

function insere_ordenado_no_array(obj, array, i) {	// insere obj, em array, na posicao i

	if (!array[i]) {
		array[i] = obj;
		return;

	} else {

		var obj2 = array[i];
		array[i] = 	event_less(obj, obj2) ? obj : obj2;
		insere_ordenado_no_array( event_less(obj, obj2) ? obj2 : obj , array, i + 1 );
	}

}

function Events_eventsOnDate(date)
{
	return (this.dates[getDateKey(date)]);
}
function Events()
{
	this.dates = new Array();
	this.events = new Array();
	this.addEvent = Events_addEvent;
	this.eventsOnDate = Events_eventsOnDate;

}