ctrCalendario.prototype = new Calendario();
ctrCalendario.prototype.cunstructor = ctrCalendario;

function ctrCalendario( m, y, dfp )
{
	this.setSelectedMonth( m );
	this.setSelectedYear( y );

	if( arguments.length > 2 && dfp != null )
		this.setDateFormatPattern( dfp );

        this.visible = false;
        this.left = 0;
        this.top = 0;

        this.element = null;
        this.currentObjectUnderMouse = null;

        this.codeStatement = new Object();
        this.codeStatement['selectDay'] = new Object();

        this.codeStatement['selectDay']['AfterBegin'] = ';';
        this.codeStatement['selectDay']['BeforeEnd'] = ';';

	this.init();
}

ctrCalendario.prototype.setCodeStatement = function( f, w, cs )
{
	this.codeStatement[f][w] = cs;
};

ctrCalendario.prototype.getCodeStatement = function( f, w )
{
	return( this.codeStatement[f][w] );
};

ctrCalendario.prototype.show = function()
{
	this.move();

	this.element.style.display = 'inline';

	this.visible = true;
};

ctrCalendario.prototype.hide = function()
{
	this.element.style.display = 'none';

	this.visible = false;
};

ctrCalendario.prototype.init = function()
{
	var objDiv = document.createElement( "DIV" );

        objDiv.id = "ctrCalendario";
        objDiv.style.position = "absolute";
        objDiv.style.display = "none";

        document.body.appendChild( objDiv );

        this.element = objDiv;
        this.element.objWrapper = this;

        this.move();

        this.element.ownerDocument.onmousemove = function( event )
        {
        	this.getElementById('ctrCalendario').objWrapper.currentObjectUnderMouse = event.target;
        }

        this.element.ownerDocument.onblur = function()
        {
        	var objCal = this.getElementById('ctrCalendario').objWrapper;
        	var obj = objCal.currentObjectUnderMouse;
        	var blnHide = true;

        	while( obj && obj != document.body )
		{
			if( obj.id == objCal.element.id )
				blnHide = false;

			obj = obj.parentNode;
		}

        	if( blnHide )
        		objCal.hide();
        };

        this.element.ownerDocument.onmousedown = function( event )
        {
        	var objCal = this.getElementById('ctrCalendario').objWrapper;
        	var coum = objCal.currentObjectUnderMouse;
        	var obj = objCal.currentObjectUnderMouse;

        	while( obj && obj != objCal.element && obj != document.body )
			obj = obj.parentNode;

        	if( obj == objCal.element )
        	{
        		var e = document.createEvent( "MouseEvents" );

        		e.initMouseEvent(
        					"mousemove",	// typeArg
        					true,
        					true,
        					self,		// view
        					1,		// detail
        					event.screenX,
        					event.screenY,
        					event.clientX,
        					event.clientY,
        					event.ctrlKey,
        					event.altKey,
        					event.shiftKey,
        					event.metaKey,
        					void(0),	// button
        					void(0)		// relatedTarget
        				);

        		obj.dispatchEvent( e );
        	}
        	else if( objCal.visible )
        	{
        		objCal.hide();
        	}
        };
};

ctrCalendario.prototype.move = function( x, y )
{
	if( arguments.length < 1 || x == null )
		x = this.left;

	if( arguments.length < 2 || y == null )
		y = this.top;

	this.element.style.left = this.left = x;
	this.element.style.top = this.top = y;
};

ctrCalendario.prototype.oncurrmonth = function() { return( true ); };

ctrCalendario.prototype.currMonth = function()
{
	if( this.oncurrmonth() )
	{
		Calendario.prototype.currMonth.apply( this, arguments );
		this.create();
	}
};

ctrCalendario.prototype.onnextmonth = function() { return( true ); };

ctrCalendario.prototype.nextMonth = function()
{
	if( this.onnextmonth() )
	{
		Calendario.prototype.nextMonth.apply( this, arguments );
		this.create();
	}
};

ctrCalendario.prototype.onprevmonth = function() { return( true ); };

ctrCalendario.prototype.prevMonth = function()
{
	if( this.onprevmonth() )
	{
		Calendario.prototype.prevMonth.apply( this, arguments );
		this.create();
	}
};

ctrCalendario.prototype.create = function()
{
	var rowCount = 0;
	var numRows = 0;
	var sOut = new String();
	var i;
	var numBlankDay;

	sOut = '<table border="0" cellpadding="1" cellspacing="0" class="calCalendar" width="225">';

	//
	// Table header (month/year)
	//
	sOut += '<tr class="calTitleBar"><td colspan="6" align="left">&nbsp;' + this.getMonth() + ' ' + this.getSelectedYear() + '</td>';
	sOut += '<td align="right"><A HREF="javascript:void(0);" onFocus="blur();" onClick="document.getElementById(\'ctrCalendario\').objWrapper.close(); return false;" title="' + this.getTooltip(0) + '">X</A></td>';
	sOut += '</tr>';

	//
	// abbreviated day names
	//
	sOut += '<tr class="calDayOfWeekHeader">';
	for( i = 0 ; i < 7 ; i++ )
		sOut += '<td class="calDayOfWeekHeader">' + this.getDayOfWeek(i).substring( 0, 3 ) + '</td>';

	sOut += '</tr>';

	//
	// Start of BODY
	//
	sOut += '<tr class="bodyMain">';
	numRows++;

	//
	// pad the blank days at the beginning of the month
	//
	if( this.getFirstDay() >= this.getFirstDayOfWeek() )
		numBlankDay = this.getFirstDay() - this.getFirstDayOfWeek();
	else
		numBlankDay = 7 - (this.getFirstDayOfWeek() - this.getFirstDay());

	for( i = 0 ; i < numBlankDay ; i++ )
	{
		rowCount++;
		sOut += '<td class="calBlankDay">&nbsp;</td>';
	}

	this.dayCount = 1;

	while( this.dayCount <= this.getLastDayOfMonth() )
	{
		//
		// Display new row after each 7 day block.
		//
		if( rowCount % 7 == 0 && (this.dayCount != 1 || numBlankDay != 0) )
		{
			sOut += '</tr>\n<tr class="bodyMain">';
			numRows++ ;
		}

		var strClassName = '';

		if( this.isToday(this.dayCount) )
			strClassName = 'calToday';
		else if( this.isFestiveDay(this.dayCount) )
			strClassName = 'calFestiveDay';
		else if( this.isSaturday(this.dayCount) )
			strClassName = 'calSaturday';
		else if( this.isSunday(this.dayCount) )
			strClassName = 'calSunday';
		else
			strClassName = 'calDay';

		//
		// Insert the Date.
		//
		sOut += '<td id="'+this.getSelectedYear() + '_' + this.getSelectedMonth()+'_'+this.dayCount+'" align="center" CLASS="' + strClassName + '" onMouseOver="this.className = this.className + \'_hover\';" onMouseOut="this.className = this.className.substring(0, this.className.length-\'_hover\'.length);"';
		sOut += ' onClick="document.getElementById(\'ctrCalendario\').objWrapper.selectDay(' + this.getSelectedYear() + ',' + this.getSelectedMonth() + ',' + this.dayCount + ');">';
//		sOut += '<A HREF="javascript:void(0);" onFocus="blur()"';
//		sOut += ' onClick="document.getElementById(\'ctrCalendario\').objWrapper.selectDay(' + this.getSelectedYear() + ',' + this.getSelectedMonth() + ',' + this.dayCount + ');"';
//		sOut += ' class="' + strClassName + '">' + this.dayCount + '</A>';
		sOut += this.dayCount;
		sOut += '</td>';

		this.dayCount++;
		rowCount++ ;
	}

	//
	// pad the blank days at the end of the month.
	//
	while( rowCount % 7 != 0 )
	{
		rowCount++ ;
		sOut += '<td class="calBlankDay">&nbsp;</td>';
	}

	//
	// Se necessaria aggiungo una riga vuota
	//
	while( rowCount < (6*7) )
	{
		if( rowCount % 7 == 0 )
	    	{
	    	    sOut += '</tr>\n<tr>';
	    	    numRows++ ;
	    	}

	    	rowCount++ ;
		sOut += '<td CLASS="calBlankDay">&nbsp;</td>';
	}

	sOut += '</tr>';

	//
	// Calendar Navigator
	//
	sOut += '<tr>';
	sOut += '<td colspan="2" align="left">';
	sOut += '<A HREF="javascript:void(0);" onFocus="blur();" onClick="document.getElementById(\'ctrCalendario\').objWrapper.prevMonth(); return false;" class="calNavigator" onMouseOver="this.className = \'calNavigator_hover\';" onMouseOut="this.className = \'calNavigator\';" title="' + this.getTooltip(1) + '"/>&lt;&lt;</A>';
	sOut += '</td>';
	sOut += '<td colspan="3" align="center">';

	if( this.isToday(this.getCurrentDay()) )
		sOut += '<A HREF="javascript:void(0);" onFocus="blur();" onClick="document.getElementById(\'ctrCalendario\').objWrapper.selectDay(' + this.getSelectedYear() + ',' + this.getSelectedMonth() + ',' + this.getCurrentDay() + '); return false;" class="calNavigator" onMouseOver="this.className = \'calNavigator_hover\';" onMouseOut="this.className = \'calNavigator\';" title="' + this.getTooltip(4) + '"/>[ O ]</A>';
	else
		sOut += '<A HREF="javascript:void(0);" onFocus="blur();" onClick="document.getElementById(\'ctrCalendario\').objWrapper.currMonth(); return false;" class="calNavigator" onMouseOver="this.className = \'calNavigator_hover\';" onMouseOut="this.className = \'calNavigator\';" title="' + this.getTooltip(3) + '"/>[ O ]</A>';

	sOut += '</td>';
	sOut += '<td colspan="2" align="right">';
	sOut += '<A HREF="javascript:void(0);" onFocus="blur()" onClick="document.getElementById(\'ctrCalendario\').objWrapper.nextMonth(); return false;" class="calNavigator"  onMouseOver="this.className = \'calNavigator_hover\';" onMouseOut="this.className = \'calNavigator\';" title="' + this.getTooltip(2) + '"/>&gt;&gt;</A>';
	sOut += '</td>';
	sOut += '</tr>';

	sOut += '<tr><td colspan="7"></td></tr>';

	sOut += '</table>';

	//
	// Render the calendar
	//
	this.write( sOut );
};

ctrCalendario.prototype.write = function( s )
{
	this.element.innerHTML = s;
};

ctrCalendario.prototype.onclose = function() { return( true ); };

ctrCalendario.prototype.close = function()
{
	if( this.onclose() )
		this.hide();
};

ctrCalendario.prototype.onselectday = function(annoOms, mese, giorno, ore, minuti, secondi, ms) { return( true ); };

ctrCalendario.prototype.selectDay = function( annoOms, mese, giorno, ore, minuti, secondi, ms )
{
	eval( this.getCodeStatement('selectDay', 'AfterBegin') );

	if( ctrCalendario.prototype.onselectday.apply(this, arguments) )
	{
		Calendario.prototype.selectDay.apply( this, arguments );
		this.close();
	}

	eval( this.getCodeStatement('selectDay', 'BeforeEnd') );
};

/*
	e	=>	event
	dfp	=>	Date Format Pattern
	csab	=>	Code Statement After Begin per il metodo selectDay
	csbe	=>	Code Statement Before End per il metodo selectDay
*/
ctrCalendario.prototype.exec = function( e, dfp, csab, csbe )
{
	if( e )
		event = e;

	if( arguments.length > 1 && dfp != null )
		setDateFormatPattern( dfp );

	if( arguments.length > 2 && csab != null )
		this.setCodeStatement( 'selectDay', 'AfterBegin', csab );

	if( arguments.length > 3 && csbe != null )
		this.setCodeStatement( 'selectDay', 'BeforeEnd', csbe );

	this.create();

	this.show(); // 1° Chiamata serve a mostrare l'oggetto in modo che l'altezza e larghezza siano lette correttamente

	var iHorizontalPadding = 5;
	var iVerticalPadding = 0;

	//
	// Recupero le coordinate assolute dell'oggetto sul quale ho cliccato
	//
	var obj = event.target;
	var srcOffsetWidth = obj.offsetWidth;
	var srcOffsetHeight = obj.offsetHeight;
	var srcX = window.pageXOffset + obj.x;
	var srcY = window.pageYOffset + obj.y;

	//
	// Recupero le coordinate relative alla porzione di pagina che si vede dal browser dell'oggetto sul quale ho cliccato
	//
	var srcClientX = obj.x;
	var srcClientY = obj.y;

	var x;
	var y;

	//
	// self.innerWidth/offsetHeight contengono la larghezza/altezza della porzione di pagina che si vede dal browser
	//

//	alert( self.innerWidth + " - ( " + srcClientX + " + " + srcOffsetWidth + " + " + iHorizontalPadding + " ) > " + this.element.offsetWidth );

	if( self.innerWidth-(srcClientX+srcOffsetWidth+iHorizontalPadding) > this.element.offsetWidth )
	{
		x = srcX + srcOffsetWidth + iHorizontalPadding;
	}
	else
	{
		x = srcX - iHorizontalPadding - this.element.offsetWidth;
	}

//	alert( self.innerHeight + " - ( " + srcClientY + " + " + iVerticalPadding + " ) > " + this.element.offsetHeight );

	if( self.innerHeight-(srcClientY+iVerticalPadding) > this.element.offsetHeight )
	{
		y = srcY + iVerticalPadding;
	}
	else
	{
		y = srcY - iVerticalPadding - this.element.offsetHeight;
	}

//	alert( x + "\t" + y );

	this.move( x, y );

	this.show(); // 2° Chiamata serve a riposizionare
};
