// JavaScript Document
/**
 * Deaktiviert alle Kalender.
 * @author Markus Hanses
 */
function deactAllCalendars()
{
	if (window.A_CALENDARS) {
		for (var i = 0; i < window.A_CALENDARS.length; i++) 
		{
			var calendar = window.A_CALENDARS[i];
			var id = calendar.getCalendarId();
			calendar.setVisible(false);
		}
	}
}


function CalendarView()
{
  this.startDate=new Date();
  this.cal = new GregorianCalendar();
  this.calStartDate=null;
  this.adjustDate=null;
  this.startDay=0;
  this.dates=new Array();
  this.id='';
  this.parentId;
  
  this.colHeight=18;
  this.colWidth=15;
  this.height=140;
  this.width=120;
  this.cellMargin=2;
  
  this.marginWidth=Math.round(this.colWidth/2);
  this.zIndex=60;
  
  this.top=0;
  this.left=0;
  this.listeners=new Array();
  this.defaultVisibility='';
  this.clickHandler;
  this.selectionModel=new CalSelectionModel();
  
  this.visible=false;
  
  this.days=new Array("So", "Mo", "Di", "Mi",
                          "Do", "Fr", "Sa");
  this.months=new Array("Januar","Februar","März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember");
  
  this.defaultImages=new Array('url(img/cell_begin1.gif)','url(img/cell_end1.gif)','url(img/cell_begin2.gif)', 
  'url(img/cell_end2.gif)','img/l_shift.jpg','img/r_shift.jpg' );
  this.images=new Array();
  this.images['cal_day_cell_begin']=this.defaultImages[0];
  this.images['cal_day_cell_end']=this.defaultImages[1];
  this.images['cal_dayout_cell_begin']=this.defaultImages[2];
  this.images['cal_dayout_cell_end']=this.defaultImages[3];
  this.images['l_shift']=this.defaultImages[4];
  this.images['r_shift']=this.defaultImages[5];
  this.dateIds=new Array();
  
 	if (!window.A_CALENDARS)
		window.A_CALENDARS = [];
	this.c_id = window.A_CALENDARS.length;
	window.A_CALENDARS[this.c_id] = this;
}
/**
 * Gibt den Array Index des registrierten Objekts als ID zureuck.
 * @author Markus Hanses
 */
CalendarView.prototype.getCalendarId=function()
{
	return this.c_id;
}
/**
 * Deaktiviert die anderen registrierten Kalender.
 * @author Markus Hanses
 */
CalendarView.prototype.deactOtherCalendars=function()
{
	for (var i = 0; i < window.A_CALENDARS.length; i++) 
	{
		var calendar = window.A_CALENDARS[i];
		var id = calendar.getCalendarId();
		if (id != this.c_id)
		{
			calendar.setVisible(false);
		}
	}
}

CalendarView.prototype.setDayList=function(anArray)
{ 
  this.days=anArray;
}

CalendarView.prototype.setMonthList=function(anArray)
{ 
  this.months=anArray;
}

CalendarView.prototype.initSize=function(anArray)
{
  	this.height=anArray['height'];
  	this.width=anArray['width'];
  	var addition = 0;
	if (navigator.appName.indexOf("Explorer") != -1)
	{
	    addition = 5;
	} else {}
	this.height = this.height + addition;
	this.width = this.width + addition;  	
  	this.colHeight=anArray['colHeight'];
  	this.colWidth= anArray['colWidth'];
  	this.cellMargin = anArray['cellMargin'];
}

CalendarView.prototype.setDimension=function(aHeight, aWidth, aColHeight, aColWidth, aMargin)
{
  this.height=aHeight;
  this.width=aWidth;
  this.colHeight=aColHeight;
  this.colWidth=aColWidth;
  this.cellMargin = aMargin;
}

CalendarView.prototype.setClickHandler=function(aValue)
{
  this.clickHandler = new ClickHandler(this, aValue);
}

CalendarView.prototype.getIsVisible=function()
{
  return this.visible;
}

CalendarView.prototype.setDefaultVisibility=function(aValue)
{
  this.defaultVisibility=aValue;
}

CalendarView.prototype.setVisible=function(aValue)
{

  if (aValue=='true' || aValue==true)
  {
    this.visible=true;
  }
  else
  {
    this.visible=false;
  }
  var theElement=document.getElementById(this.id);
  if (theElement)
  {  
    if (this.visible)
      theElement.style.visibility='visible';
    else
      theElement.style.visibility='hidden';
  }
}

/**
 * View Element to what this calendar will be bind.
 * @param anID Parameter of the element that will be used to bind the calendar 
 *  into the view. 
 */ 
CalendarView.prototype.setParent=function(anID)
{
  this.parentId=anID;
  this.id='clr_'+anID;
  window[this.id]=this;
}


/**
 * Changes date and view to the specifed Date
 * @param aDate new Date to be adjusted to.  
 *  
 */
CalendarView.prototype.selectDate=function(aDate)
{
  //alert('Setting new Date:'+this.cal.print(aDate)+" oldDate="+this.startDate);
  var theNewM =aDate.getMonth();
  var theOldM = this.startDate.getMonth();
  var theCompare = this.cal.compare(aDate, this.startDate);
  if (theCompare != 0)
  {
    this.setStartDate(aDate);
    this.write();
  }
  else
  {
    var theDate = aDate;
  }
  var theId = this.dateIds[this.cal.print(aDate)];
  if (theId)
  {
    this.selectionModel.select(theId, aDate);
    var theCalEvent = new CalEvent(this, aDate,'SELECT');
    this.notifyListener(theCalEvent);
  }
  
}

/**
 * Changes date and view to the specifed Date
 * @param aDate new Date to be adjusted to.  
 *  
 */
CalendarView.prototype.selectMonth=function(aDate)
{
  this.setStartDate(aDate);
  this.write();
}
 
/**
 * Sets the start date attribute.
 * @param aDate new StartDate - to be set before building up the calendar. 
 */
CalendarView.prototype.setStartDate=function(aDate)
{
  this.startDate=aDate;
} 

/**
 *
 * Calculates the Start Date that will be visible as first day on the calendar.
 *   
 */
CalendarView.prototype.calcStartDate=function(aDate)
{
  var theDay = this.startDate.getDate();
  
  var theValue = 1-Math.abs(theDay);
  
  var theNewDate = this.cal.shift(theValue, this.startDate);
  
  if (theNewDate.getDay()>1)
  {
    theValue=1-theNewDate.getDay();
    theNewDate=this.cal.shift(theValue, theNewDate);
  }
  else if (theNewDate.getDay()==0)
  {
    theValue=0-theNewDate.getDay();
    theNewDate=this.cal.shift(-6, theNewDate);
  }
  
  return theNewDate;
}

/**
 */
CalendarView.prototype.adjustDay=function(aDate)
{
  var theDay = aDate.getDate();
  var theYear = aDate.getFullYear();
  var theMonth = aDate.getMonth();
  var theNewDate = new Date(theYear, theMonth, 15);
  return theNewDate;
}

CalendarView.prototype.write=function()
{  
  this.calStartDate= this.calcStartDate(this.startDate);
  var theElement= document.getElementById(this.parentId);
  if (theElement != null)
  {
    theElement.innerHTML=this.getParentElement().write();
  }
  else alert(this.parent+" is null");
  
  
}

CalendarView.prototype.getVisibility=function()
{
  return this.defaultVisibility;
}

CalendarView.prototype.getParentElement=function()
{
  var theElement = new DIVElement();
  var theVisible = (this.getIsVisible() || this.defaultVisibility=='visible') ? 'visible' : 'hidden';
  
  theElement.addAttribute('class', 'calendar_frame');
  theElement.addAttribute('id', this.id);
  theElement.addStyleElement('position', 'absolute');
  theElement.addStyleElement('top', this.top+'px');
  theElement.addStyleElement('left', this.left+'px');
  theElement.addStyleElement('visibility', theVisible);
  theElement.addStyleElement('z-index', this.zIndex);
  theElement.addStyleElement('height', this.height+'px');
  //alert("Setting width cal="+this.width+);
  theElement.addStyleElement('width', this.width+'px');
  //theElement.addStyleElement('background-color', 'white');
  
  var thePElement = new PElement();
  thePElement.addContent(' ');
  theElement.addElement(thePElement);
  
  theElement.addElement(this.buildUp());
  
  return theElement;
}

CalendarView.prototype.buildUp=function()
{
  var theId = null;
  var theElement = new DIVElement();
  theElement.addAttribute('class', 'cal_parent');
  theElement.addAttribute('id', this.id+'_cols');
  theElement.addStyleElement('position', 'absolute');
  theElement.addStyleElement('top', 5+'px');
  theElement.addStyleElement('left', 4+'px');
  theElement.addStyleElement('height', this.height+'px');
  theElement.addStyleElement('width', this.width+'px');
  theElement.addStyleElement('z-index', this.zIndex+1);
  var theStart=0;
  
  var theRow = 0;
  
  theElement.addElement(this.createMonthHeader(theRow, this.marginWidth , this.startDate, this.id+'_month'));
  
  var theCol = 0;
  
  theRow++;
  var theRowH = this.createRow(theRow, this.startDate, 0);
  for (var j=0;j<7; j++)
  {
    theRowH.addElement(this.createHeader(theRow, (j+1), j, ''));
  }
  theElement.addElement(theRowH);
  
  var theRowElement=null;
  var theEndElement = null;
  this.dateIds=new Array();
  for (var i=0;i<35; i++)
  {
    theCol++;
    var theMod=i%7;
    var theDate =this.cal.shift(i,this.calStartDate);
    
    if (theMod==0)
    {
      theRow++;
      theCol=0;
      theRowElement = this.createRow(theRow, theDate, theId);
      theEndElement = this.createEndElement(theRow, theCol, theDate, 'begin');
      theElement.addElement(theEndElement);
      theCol=1;
    }
    
    theId = this.id+'cal_cell_id_'+i;
    this.dateIds[this.cal.print(theDate)]=theId;
    this.dates[theId]=theDate;
    //theRowElement.addElement(this.createDay(0, theCol, theDate, theId));
    //theElement.addElement(theRowElement);
    var theLeft = ((theCol-1)*this.colWidth)+this.marginWidth;
    theElement.addElement(this.createDay(theRow, theDate, theId, theLeft));
    
    if (theMod==6)
    {
      var theEndElement = this.createEndElement(theRow, theCol+1, theDate, 'end');
      theElement.addElement(theEndElement);
    }
  }
  
  return theElement;
}

CalendarView.prototype.createRow=function(aRow, aDate, aNo)
{
  var theElement=new DIVElement();
  
  theElement.addAttribute('class', 'cal_day_cell_row');
  theElement.addStyleElement('position', 'absolute');
  theElement.addStyleElement('top', (aRow*this.colHeight)+'px');
  theElement.addStyleElement('left', (0)+'px');
  theElement.addStyleElement('height', (this.colHeight)+'px');
  theElement.addStyleElement('width', (7*this.colWidth)+'px');
  //theElement.addStyle(this.getStyle());
  
  return theElement;
}

/**
 * Returns the current selected Date.
 * @return the current selected Date or null, when no Date is selected. 
 */
CalendarView.prototype.getSelectedDate=function()
{
  return this.selectionModel.getSelectedDate();
}

CalendarView.prototype.createDay=function(aRow, aDate, aNo, aLeft)
{
  var theElement=new DIVElement();
  var theHeight=this.colHeight-this.cellMargin;
  var theTop= (aRow*this.colHeight)+Math.round(this.cellMargin/2);
  var theClassId=null;
  if (aDate.getMonth()==this.startDate.getMonth())
    theClassId='cal_day_cell_'+aDate.getDay();
  else 
    theClassId='cal_dayout_cell_'+aDate.getDay();
    
  theElement.addAttribute('class', theClassId);
  if (!this.selectionModel.inited)
  {
    this.selectionModel.addClassMapping(theClassId, theClassId+'_sel');
    this.selectionModel.addClassMapping(theClassId+'_sel', theClassId);
  }
  theElement.addAttribute('id', aNo);
  theElement.addStyleElement('position', 'absolute');
  theElement.addStyleElement('top', (theTop)+'px');
  theElement.addStyleElement('left', (aLeft)+'px');
  theElement.addStyleElement('height', (theHeight)+'px');
  theElement.addStyleElement('width', (this.colWidth)+'px');
  
  theElement.addAttribute('onmouseover','return window.'+this.id+'.notifyOnMouseOver(\''+aNo+'\')');
  theElement.addAttribute('onmouseout','return window.'+this.id+'.notifyOnMouseOut(\''+aNo+'\')');
  theElement.addAttribute('onclick','return window.'+this.id+'.notifyOnClick(\''+aNo+'\')');
  
  var thePElement=new PElement();
  thePElement.addContent((aDate.getDate()));
  /*
  var thePosElement=new DIVElement();
  thePosElement.addStyleElement('position', 'absolute');
  thePosElement.addStyleElement('top', (2)+'px');
  thePosElement.addStyleElement('text-align', 'center');
  thePosElement.addStyleElement('height', (theHeight)+'px');
  thePosElement.addStyleElement('width', (this.colWidth)+'px');
  
  thePosElement.addAttribute('class', 'cal_p_cell');
  thePosElement.addElement(thePElement);
  theElement.addElement(thePosElement);
  */
  theElement.addElement(thePElement);
  return theElement;
}

CalendarView.prototype.createEndElement=function(aRow, aCol, aDate, aPos)
{
  
  var theElement=new DIVElement();
  var theHeight=this.colHeight-this.cellMargin;
  var theTop= (aRow*this.colHeight)+Math.round(this.cellMargin/2);
  var theLeft = 0;
  if(aCol >0)
  {
   theLeft = ((aCol-1)*this.colWidth)+this.marginWidth;
  }
  var theClassId=null;
  
  
  if (aDate.getMonth()==this.startDate.getMonth())
    theClassId='cal_day_cell_'+aPos;
  else 
    theClassId='cal_dayout_cell_'+aPos;
  
  var theImg=this.images[theClassId];
    
  theElement.addAttribute('class', theClassId);
  theElement.addStyleElement('position', 'absolute');
  theElement.addStyleElement('top', (theTop)+'px');
  
  theElement.addStyleElement('left', theLeft+'px');
  theElement.addStyleElement('height', (theHeight)+'px');
  theElement.addStyleElement('width', (this.marginWidth)+'px');
  if (theImg)
  theElement.addStyleElement('background-image', theImg);
  
  //'url(img/cell_end2.jpg)');
  //theElement.addStyle(this.getStyle());
  
  var thePElement=new PElement();
  thePElement.addAttribute('class', 'cal_day_no');
  thePElement.addContent(' ');
  theElement.addElement(thePElement);
  return theElement;
}



CalendarView.prototype.createMonthHeader=function(aTop, aLeft, aDate, aNo)
{
  var theRow = this.createRow(aTop, aDate, aNo);
  var theHeight=this.colHeight-this.cellMargin;
  var theTop= 0; //(aRow*this.colHeight)+Math.round(this.cellMargin/2);
  
  var theParent = new DIVElement();
  var theWidth= this.colWidth *7;
  theParent.addAttribute('class', 'cal_header_month');
  //theElement.addAttribute('id', aNo);
  theParent.addStyleElement('position', 'absolute');
  theParent.addStyleElement('top', theTop+'px');
  theParent.addStyleElement('left', (aLeft)+'px');
  theParent.addStyleElement('height', (theHeight)+'px');
  theParent.addStyleElement('width', theWidth+'px');
  theParent.addStyleElement('z-index', this.zIndex+2);
  //theParent.addStyle(this.getStyle());

  var theLElement=new DIVElement();
  theLElement.addAttribute('class', 'cal_header_month_L');
  theLElement.addAttribute('id', 'cal_header_month_L'+aNo);
  theLElement.addStyleElement('position', 'absolute');
  theLElement.addStyleElement('top', (theTop)+'px');
  theLElement.addStyleElement('left', '-5' + 'px'); // Abstand nach links verschoben.
  theLElement.addStyleElement('height', (theHeight)+'px');
  theLElement.addStyleElement('width', (this.colWidth/2)+'px'); // Halbieren der Breite
  theLElement.addStyleElement('z-index', this.zIndex+3);
  
  var thePElement = new PElement();
  thePElement.addContent('L');
  
  
  var theLIElement = new ElementTag('img');
  theLIElement.addAttribute('src',this.images['l_shift']);
  theLElement.addElement(theLIElement);
  
  theParent.addElement(theLElement);
  
  var theElement=new DIVElement();
  theElement.addAttribute('class', 'cal_header_month_M');
  //theElement.addAttribute('id', aNo);
  theElement.addStyleElement('position', 'absolute');
  theElement.addStyleElement('top', (theTop)+'px');
  theElement.addStyleElement('left', (this.colWidth / 3)+'px'); // Reduzieren linken Abstands 
  theElement.addStyleElement('height', (theHeight)+'px');
  theElement.addStyleElement('width', (6*this.colWidth)+'px'); // Erweitern der Breite um das gewonnene Column aus den Halbierungen.
  //theElement.addStyle(this.getStyle());
  theElement.addStyleElement('z-index', this.zIndex+3);
  thePElement = new PElement();
  var theFullYear = aDate.getFullYear();
  thePElement.addContent(this.months[aDate.getMonth()] +' '+theFullYear );
  
  theElement.addElement(thePElement);
  theParent.addElement(theElement);

  var theRElement=new DIVElement();
  theRElement.addAttribute('class', 'cal_header_month_L');
  theRElement.addAttribute('id', 'cal_header_month_L'+aNo);
  theRElement.addStyleElement('position', 'absolute');
  theRElement.addStyleElement('top', (theTop)+'px');
  theRElement.addStyleElement('right', '-5' +'px'); // Abstand nach rechts verschoben
  theRElement.addStyleElement('height', (theHeight)+'px');
  theRElement.addStyleElement('width', (this.colWidth /2)+'px'); // Halbieren der Breite
  theRElement.addStyleElement('z-index', this.zIndex+3);
  
  thePElement = new PElement();
  thePElement.addContent('');
  
  
  var theRIElement = new ElementTag('img');
  theRIElement.addAttribute('src',this.images['r_shift']);
  //theRIElement.addAttribute('src',this.images['r_shift']);
  
  theRIElement.addStyleElement('position','absolute');
  theRIElement.addStyleElement('right','0px');
  theRElement.addElement(theRIElement);
  theParent.addElement(theRElement);
  
  theLElement.addAttribute('onmouseover','return window.'+this.id+'.notifyOnMouseOver(\''+aNo+'\')');
  theLElement.addAttribute('onmouseout','return window.'+this.id+'.notifyOnMouseOut(\''+aNo+'\')');
  theLElement.addAttribute('onclick','return window.'+this.id+'.shiftLeft()');

  theRElement.addAttribute('onmouseover','return window.'+this.id+'.notifyOnMouseOver(\''+aNo+'\')');
  theRElement.addAttribute('onmouseout','return window.'+this.id+'.notifyOnMouseOut(\''+aNo+'\')');
  theRElement.addAttribute('onclick','return window.'+this.id+'.shiftRight()');
  
  
  theRow.addElement( theParent);
  return theRow;
}

CalendarView.prototype.createHeader=function(aRow, aCol, aDay, aNo)
{
 
 var theValue=aDay+1;
  if (theValue==7)
    theValue=0;
  var theHeight=this.colHeight-this.cellMargin;
  var theTop= 0; //(aRow*this.colHeight)+Math.round(this.cellMargin/2);
  
  var theElement=new DIVElement();
  
  theElement.addAttribute('class', 'cal_header_cell_'+theValue);
  
  //theElement.addAttribute('id', aNo);
  theElement.addStyleElement('position', 'absolute');
  theElement.addStyleElement('top', (theTop)+'px');
  theElement.addStyleElement('left', (((aCol-1)*this.colWidth) +this.marginWidth)+'px');
  theElement.addStyleElement('height', (theHeight)+'px');
  theElement.addStyleElement('width', (this.colWidth)+'px');
  theElement.addStyleElement('z-index', this.zIndex+3);
  //theElement.addStyle(this.getStyle());
  //theElement.addAttribute('onmouseover','return window.'+this.id+'.notifyOnMouseOver(\''+aNo+'\')');
  //theElement.addAttribute('onmouseout','return window.'+this.id+'.notifyOnMouseOut(\''+aNo+'\')');
  //theElement.addAttribute('onclick','return window.'+this.id+'.notifyOnClick(\''+aNo+'\')');
  
  var thePElement=new PElement();
  thePElement.addAttribute('class', 'cal_p_cell');
  
  thePElement.addContent(this.days[theValue]);
  theElement.addElement(thePElement);
  return theElement;
}



CalendarView.prototype.notifyOnMouseOver=function(anId)
{
  document.body.style.cursor='pointer';
  if (anId!=null && anId.length>0)
  {
    var theElement=document.getElementById(anId);
  }
  
}

CalendarView.prototype.notifyOnMouseOut=function(anId)
{
  document.body.style.cursor='default';
}

CalendarView.prototype.notifyOnClick=function(anId)
{
  if (!(anId!=null && anId.length>0))
  {
    return;
  }
  document.body.style.cursor='default';
  var theDate = this.dates[anId];
  var theElement=document.getElementById(anId);
  
  this.selectionModel.select(anId, theDate);
  
  var theCalEvent = new CalEvent(this, theDate,'SELECT');  
  this.notifyListener(theCalEvent);    
}

CalendarView.prototype.shiftLeft=function()
{
  this.startDate=this.cal.shiftMonth(-1, this.adjustDay(this.startDate));
  var theOld = this.defaultVisibility;
  this.defaultVisibility='visible';
  this.write();
  this.defaultVisibility=theOld;
  var theCalEvent = new CalEvent(this, this.startDate, 'SHIFT_PREV');
  this.notifyListener(theCalEvent);
}

CalendarView.prototype.shiftRight=function()
{
  this.startDate=this.cal.shiftMonth(1, this.adjustDay(this.startDate));
  var theOld = this.defaultVisibility;
  this.defaultVisibility='visible';
  this.write();
  this.defaultVisibility=theOld;
  var theCalEvent = new CalEvent(this, this.startDate, 'SHIFT_NEXT');
  this.notifyListener(theCalEvent);
}


CalendarView.prototype.addListener=function(aListener)
{
    this.listeners[this.listeners.length]=aListener;
}

CalendarView.prototype.notifyListener=function(anEvent)
{
  if(this.listeners!=null&&this.listeners.length>0)
  { 
    for(var i = 0;i<this.listeners.length;i++)
    {
      this.listeners[i].dateSelected(anEvent);
    }
  }
}

CalendarView.prototype.getStyle=function()
{
  return "font-family:Arial, Helvetica, sans-serif; font-size:11px; ";
}

/** CalendarEvent - contains the Date selected by clicking on a Value*/

function CalEvent(aSource, aDate, anAction)
{
  this.SHIFT_PREV='SHIFT_PREV';
  this.SHIFT_NEXT='SHIFT_NEXT';
  this.SELECT='SELECT';
  this.source=aSource;
  this.date=aDate;
  this.action=anAction;
}

/** Parent element that will click */
function ClickHandler(aCalendar, anId)
{
  this.id=aCalendar.id+'_handler';
  window[this.id]=this;
  this.calendar=aCalendar;
  var theElement = document.getElementById(anId);
  if (!theElement)
  {
    alert(anId+" Element not found for handler.");
    return;
  }
  var theHandler = this;
  //todo currently just replacing the click event function.
  theElement.onclick=function()
  {
    theHandler.onSelect();
  }
  return this;
}

ClickHandler.prototype.onSelect=function()
{
  if (!this.calendar.getIsVisible())
  {
    this.calendar.setVisible(true);
	this.calendar.deactOtherCalendars();
  }
  else
  {
    this.calendar.setVisible(false);	
  }
}

function CalSelectionModel()
{
  this.classNames=new Array();
  this.inited=false;
  this.count=0;
  this.selectedElement=null;
  this.selectedDate=null;
  this.bgcolor=null; 
}

CalSelectionModel.prototype.select=function(anId, aDate)
{
  var theElement = document.getElementById(anId);
  var theClass;
  if (this.selectedElement!=null)
  {
    theClass=this.selectedElement.className;
    if (this.classNames[theClass])
    {
      theClass=this.classNames[theClass];
      this.selectedElement.className=theClass;
    }
    this.selectedElement=null;
  }
  if(theElement)
  {
    theClass=theElement.className;
    if (this.classNames[theClass])
    {
      theClass=this.classNames[theClass];
      theElement.className=theClass;
    }
    this.selectedElement=theElement;
    this.selectedDate = aDate;
  }
}

CalSelectionModel.prototype.getSelectedDate=function()
{
  return this.selectedDate;
}

CalSelectionModel.prototype.addClassMapping=function(aClass, aMapped)
{
  this.count++;
  this.classNames[aClass]=aMapped;
}
