
function Planif(name,mode,targetelement,multiselect, selected_item) {
	var self = this; 
	function calConfig() {
		self.versionNumber = '2.0.1';
		self.displayYearInitial = 1970; //the initial year to display on load
		self.displayMonthInitial = 0; //the initial month to display on load (0-11)
		self.displayYear = self.displayYearInitial;
		self.displayMonth = self.displayMonthInitial;
		self.startDay = 0; // the day the week will 'start' on: 0(Sun) to 6(Sat)
		self.selCurMonthOnly = true; //allow user to only select dates in the currently displayed month
		self.inidaylist = selected_item;
	}
	function setLang() {
		self.clearbtn_caption = 'Limpiar';
		self.clearbtn_title = 'Limpiar todas las fechas seleccionadas en el calendario';
		self.daylist = new Array('7-8', '8-9','9-10','10-11','11-12','12-13','13-14','14-15','16-17','17-18','18-19','19-20','20-21', '21-22');
		self.weeklist = new Array('Lunes','Martes','Miércoles','Jueves','Viernes','Sábado','Domingo');
	}
	function setDays() {
		self.daynames = new Array();
		var j=0;
		for(var i=self.startDay;i<self.startDay + 14;i++) {
			self.daynames[j++] = self.daylist[i];
		}
		self.monthDayCount = new Array(31,((self.curDate.getFullYear() - 2000) % 4 ? 28 : 29),31,30,31,30,31,31,30,31,30,31);
	}
	function createCalendar() {
		var tbody, tr, td;
		self.calendar = document.createElement('table');
		self.calendar.setAttribute('id',self.name+'_calendar');
		setClass(self.calendar,'calendar');
		self.calendar.style.display = 'none'; //default to invisible
		addEventHandler(self.calendar,'selectstart', function() {return false;});
		addEventHandler(self.calendar,'drag', function() {return false;});
		tbody = document.createElement('tbody');


		tr = document.createElement('tr');
		td = document.createElement('td');
		self.calendar.celltable = document.createElement('table');
		setClass(self.calendar.celltable,'cells');
		self.calendar.celltable.appendChild(createDayHeading());
		self.calendar.celltable.appendChild(createCalCells());
		td.appendChild(self.calendar.celltable);
		tr.appendChild(td);
		tbody.appendChild(tr);

		//create the calendar footer
		tr = document.createElement('tr');
		td = document.createElement('td');
		td.appendChild(createFooter());
		tr.appendChild(td);
		tbody.appendChild(tr);

		self.calendar.appendChild(tbody);

		addEventHandler(self.calendar,'mouseover',cal_onmouseover);
		addEventHandler(self.calendar,'mouseout',cal_onmouseout);
	}

	function createFooter() {
		var container = document.createElement('div');
		var clearSelected = document.createElement('input');
		clearSelected.setAttribute('type','button');
		clearSelected.setAttribute('value',self.clearbtn_caption);
		clearSelected.setAttribute('title',self.clearbtn_title);
		clearSelected.owner = self;
		addEventHandler(clearSelected,'click',function() {self.resetSelections(false);});
		container.appendChild(clearSelected);
		return container;
	}

	function createDayHeading() {
		self.calHeading = document.createElement('thead');
		setClass(self.calHeading,'caldayheading');
		var tr = document.createElement('tr'), th;
		self.cols = new Array(false,false,false,false,false,false,false);

		th = document.createElement('th');
		setClass(th,'wkhead');
		tr.appendChild(th);

		for(var dow=0;dow<14;dow++) {
			th = document.createElement('th');
			th.appendChild(document.createTextNode(self.daynames[dow]));
			if(self.selectMultiple) {
				th.headObj = new CalHeading(self,th,(dow + self.startDay < 14 ? dow + self.startDay : dow + self.startDay - 14));
			}
			tr.appendChild(th);
		}
		self.calHeading.appendChild(tr);
		return self.calHeading;
	}
	function createCalCells() {
		self.rows = new Array(false,false,false,false,false,false);
		self.cells = new Array();
		var row = -1, totalCells = 105;
		var sdt = new Date(self.displayYear,self.displayMonth,1);
		sdt.setDate(1);
		self.calCells = document.createElement('tbody');
		var tr,td;
		var cellIdx = 0, cell, week, dayval;

		for(var i=0;i<totalCells;i++) {
			if(i % 15 == 0) {
				row++;
				week = self.weeklist[row];
				tr = document.createElement('tr');
				td = document.createElement('td');
				if(self.selectMultiple) { 
					td.weekObj = new WeekHeading(self,td,week,row)
				}
				else {
					setClass(td,'wkhead');
				}

				td.appendChild(document.createTextNode(week));
				tr.appendChild(td);
				i++;
			}
			dayval = sdt.getDate();
			td = document.createElement('td');
			td.appendChild(document.createTextNode(''));
			cell = new CalCell(self,td,sdt,row,week);
			self.cells[cellIdx] = cell;
			td.cellObj = cell;
			tr.appendChild(td);
			self.calCells.appendChild(tr);
			self.reDraw(cellIdx++); 
			sdt.setDate(dayval + 1);
		}
		return self.calCells;
	}

	function setClass(element,className) {
		element.setAttribute('class',className);
		element.setAttribute('className',className); //<iehack>
	}
	function setCellProperties(cellindex) {
		var cell = self.cells[cellindex];
		var date;
		idx = self.dateInArray(self.dates,cell.date);
		if(idx > -1) {
			date = self.dates[idx]; 
			cell.date.selected = date.selected || false;
			cell.date.type = date.type;
		}
		else {
			cell.date.selected = false;
		}
		cell.setClass();
	}
	function cal_onmouseover() {
		self.mousein = true;
	}
	function cal_onmouseout()	{
		self.mousein = false;
	}
	function updateSelectedDates() {
		var idx = 0;
		self.selectedDates = new Array();
		for(i=0;i<self.dates.length;i++) {
			if(self.dates[i].selected) {
				self.selectedDates[idx++] = self.dates[i];
			}
		}
	}
	self.dateInArray = function(arr,searchVal,startIndex) {
		startIndex = (startIndex != null ? startIndex : 0); //default startIndex to 0, if not set
		for(var i=startIndex;i<arr.length;i++) {
			if(searchVal.getUeDay() == arr[i].getUeDay()) {
				return i;
			}
		}
		return -1;
	};
	self.show = function ()	{
		self.calendar.style.display = 'block'; 
		self.visible = true;
	};
	self.addDates = function (dates,redraw) {
		var i;
		for(i=0;i<dates.length;i++) {
			if(self.dateInArray(self.dates,dates[i]) == -1) { 
				self.dates[self.dates.length] = dates[i];
			}
		}
		updateSelectedDates();
		if(redraw != false) {
			self.reDraw();
		}
	};
	self.removeDates = function (dates,redraw) {
		var idx;
		for(var i=0;i<dates.length;i++) {
			idx = self.dateInArray(self.dates,dates[i]);
			if(idx != -1) { 
				self.dates.splice(idx,1);
			}
		}
		updateSelectedDates();
		if(redraw != false) {
			self.reDraw();
		}
	};
	//-----------------------------------------------------------------------------
	self.selectDates = function (inpdates,selectVal,redraw,removeothers) {
		var i, idx;
		if(removeothers == true) {
			for(i=0;i<self.dates.length;i++) {
				self.dates[i].selected = false;
			}
		}
		for(i=0;i<inpdates.length;i++) {
			idx = self.dateInArray(self.dates,inpdates[i]);
			if(selectVal == true) {
				inpdates[i].selected = true;
				if(idx == -1) { //if the date does not exist in the calendar's dates array, add it
					self.dates[self.dates.length] = inpdates[i];
				}
				else { //if not, just select it
					self.dates[idx].selected = true;
				}
			}
			else { //if deselecting...
				if(idx > -1) { //if the date is found, deselect and/or remove it from the calendar's dates array
					self.dates[idx].selected = inpdates[i].selected = false;
				//	if(self.dates[idx].type == 'normal') { //remove 'normal' dates from the dates array, since they're useless unless selected
						self.dates.splice(idx,1);
				//	}
				}
			}
		}
		//now rebuild the selectedDates pointer array
		updateSelectedDates();
		if(redraw != false) { //redraw the calendar if "redraw" is false or undefined
			self.reDraw();
		}
	};
	//-----------------------------------------------------------------------------
	self.sendForm = function(form,inputname) {
		var inp = inputname || 'epochdates';
		for(var i=0;i<self.dates.length;i++)
		{
			inp = document.createElement('input');
			inp.setAttribute('type','hidden');
			inp.setAttribute('name',inputname + '[]');
			inp.setAttribute('value',encodeURIComponent(self.dates[i].getUeDay()));  //default to the ISO date format
			form.appendChild(inp);
		}
	};
	//-----------------------------------------------------------------------------
	self.resetSelections = function (retMonth) {
		var dateArray = new Array();
		var dt = self.dates;
		for(var i=0;i<dt.length;i++) {
			if(dt[i].selected) {
				dateArray[dateArray.length] = dt[i];
			}
		}
		self.dates = new Array();
		self.selectDates(dateArray,false,false);
		self.rows = new Array(false,false,false,false,false,false,false);
		self.cols = new Array(false,false,false,false,false,false,false);
		retMonth == true ? self.goToMonth(self.displayYearInitial,self.displayMonthInitial) : self.reDraw();
	};

	//-----------------------------------------------------------------------------
	self.reDraw = function (index) {
		self.state = 1;
		var len = index ? index + 1 : self.cells.length;
		for(var i = index || 0;i<len;i++) {
			setCellProperties(i);
		}
		self.state = 2;
	};
	//-----------------------------------------------------------------------------
	self.getCellIndex = function(date) {
		for(var i=0;i<self.cells.length;i++) {
			if(self.cells[i].date.getUeDay() == date.getUeDay()) {
				return i;
			}
		}
		return -1;
	};

	self.state = 0;
	self.name = name;
	self.curDate = new Date();
	self.mode = mode;
	self.selectMultiple = (multiselect == true); //'false' if not true or not set at all
	self.dates = new Array();
	self.selectedDates = new Array();

	self.calendar;
	self.calHeading;
	self.calCells;
	self.rows;
	self.cols;
	self.cells = new Array();
	self.monthSelect;
	self.yearSelect;
	self.mousein = false;

	calConfig();
	setLang();
	setDays();
	createCalendar(); 
	self.tgt = targetelement;
	self.tgt.appendChild(self.calendar);

	if (self.inidaylist.length > 0){
		var dateArray = new Array();
		for(var i=0;i<self.inidaylist.length;i++) {
			dateArray[dateArray.length] = new Date(self.displayYearInitial, self.displayMonthInitial, 1+parseFloat(self.inidaylist[i]));
		}
		self.selectDates(dateArray, true, true);
	}

	self.visible = true;	
	self.state = 2; 
	self.show();
}
//-----------------------------------------------------------------------------
/*****************************************************************************/
function CalHeading(owner,tableCell,dayOfWeek) {
	//-----------------------------------------------------------------------------
	function DayHeadingonclick() {
		//reduce indirection:
		var sdates = owner.dates;
		var cells = owner.cells;
		var dateArray = new Array();
		owner.cols[dayOfWeek] = !owner.cols[dayOfWeek];
		for(var i=0;i<cells.length;i++) { 
			if(cells[i].dayOfWeek == dayOfWeek){
				dateArray[dateArray.length] = cells[i].date;
			}
		}
		owner.selectDates(dateArray,owner.cols[dayOfWeek],true);
	}
	//-----------------------------------------------------------------------------
	var self = this;
	self.dayOfWeek = dayOfWeek;
	addEventHandler(tableCell,'mouseup',DayHeadingonclick);
}
function WeekHeading(owner,tableCell,week,tableRow) {
	//-----------------------------------------------------------------------------
	function weekHeadingonclick() {
		//reduce indirection:
		var cells = owner.cells;
		var sdates = owner.dates;
		var dateArray = new Array();
		owner.rows[tableRow] = !owner.rows[tableRow];
		for(var i=0;i<cells.length;i++) {
			if(cells[i].tableRow == tableRow) { 
				dateArray[dateArray.length] = cells[i].date;
			}
		}
		owner.selectDates(dateArray,owner.rows[tableRow],true);
	}
	//-----------------------------------------------------------------------------
	var self = this;
	self.week = week;
	tableCell.setAttribute('class','wkhead');
	tableCell.setAttribute('className','wkhead'); //<iehack>
	addEventHandler(tableCell,'mouseup',weekHeadingonclick);
}
/*****************************************************************************/

function CalCell(owner,tableCell,dateObj,row,week) {
	var self = this;
	//-----------------------------------------------------------------------------
	function calCellonclick() {
		if(owner.selectMultiple == true) { 
			owner.selectDates(new Array(self.date),!self.date.selected,false);
			self.setClass(); 
		}
	}
	//-----------------------------------------------------------------------------
	function calCellonmouseover() {
		tableCell.setAttribute('class',self.cellClass + ' hover');
		tableCell.setAttribute('className',self.cellClass + ' hover');
	}
	//-----------------------------------------------------------------------------
	function calCellonmouseout() {
		self.setClass();
	}
	//-----------------------------------------------------------------------------
	self.setClass = function ()
	{
		if(self.date.selected) {
			self.cellClass = 'cell_selected';
		}
		else {
			self.cellClass = 'wkend';
		}
		tableCell.setAttribute('class',self.cellClass);
		tableCell.setAttribute('className',self.cellClass); 
	};

	self.cellClass;			
	self.tableRow = row;
	self.tableCell = tableCell;
	self.date = new Date(dateObj);
	self.date.type = 'normal'; 
	self.date.selected = false;	
	self.date.cellHTML = '';
	if(row == 0){
		self.dayOfWeek = self.date.getUeDay();
	}else{
		self.dayOfWeek = (self.date.getUeDay() - (row*14));
	}
	self.week = week;

	addEventHandler(tableCell,'click', calCellonclick);
	addEventHandler(tableCell,'mouseover', calCellonmouseover);
	addEventHandler(tableCell,'mouseout', calCellonmouseout);
	self.setClass();
}
/*****************************************************************************/
Date.prototype.getDayOfYear = function ()
{
	return parseInt((this.getTime() - new Date(this.getFullYear(),0,1).getTime())/86400000 + 1);
};

//-----------------------------------------------------------------------------
Date.prototype.getUeDay = function () 
{
	return parseInt(Math.floor((this.getTime() - this.getTimezoneOffset() * 60000)/86400000)); 
};
function addEventHandler(element, type, func) { 
	if(element.addEventListener) {
		element.addEventListener(type,func,false);
	}
	else if (element.attachEvent) {
		element.attachEvent('on'+type,func);
	}
}
