/**
 * Version: 1.0 
 * Build Date: 05.02.2010.
 * 
 * Basit Qadeer.
 *   
 * License: Licensed under The MIT License.  
 * Website: http://www.cic.de
 */


var Kalender = function CICKalender(containerId, setting) {

  // the default options.
  this.options = {
		"onSelect" : this.empty,
		"orientation" : 'horizontal' ,
		"height" : '200',
		"transition" : function(p){return -(Math.cos(Math.PI * p) - 1) / 2;},
		"width" : '150',
		"calendars" : 3,
		"language" : 'de',
		"maxDate" : '',
		"minDate" : '',
		"startDay" : 1,
		"navigationPosition": top,
		"monthSelector" : 0,
		"dateList": ''
	}

  this.DEFAULT_DATE = new Date(1970,0,1,0,0,0);
  
  if(setting !== undefined ) {
      for (var property in setting)
      this.options[property] = setting[property];
  }

  this.months = config.language[this.options['language']].months;
  this.days = config.language[this.options['language']].days;
  this.next_month = config.language[this.options['language']].next_month;
  this.previous_month = config.language[this.options['language']].previous_month;
  
	// Now
	this.d = new Date();

 	//maximum date.
 	this.maxDate = (this.options.maxDate == '') ? this.DEFAULT_DATE : this.toDate(this.options.maxDate);

 	//minimum date.
 	this.minDate = (this.options.minDate == '') ? this.DEFAULT_DATE : this.toDate(this.options.minDate);

  //adjust clander startdate according to the mindate.
  if(this.minDate > this.d) {
    this.d.setDate(this.minDate.getDate());
    this.d.setMonth(this.minDate.getMonth());
    this.d.setFullYear(this.minDate.getFullYear());
  }
  
  // access month number from current date.
  this.month = this.minDate.getMonth();
   
  // access day of month from current date.
  this.date = this.d.getDate();
  
  // access day of week from current date.
  var day = this.d.getDay();

	// keeps reference of the selected date.
	if(this.options.startDate == undefined || this.options.startDate == '')
	 this.selectedDate = '';
	else {
    this.selectedDate = this.toDate(this.options.startDate);
    this.d.setMonth(this.selectedDate.getMonth());
	}
	
	// access first day of the week from start of month.
  this.d.setDate(1);
	this.firstDay = this.d.getDay() - this.options.startDay;
	this.d.setDate(this.date);

  // access the 4-digit year from current date.
  this.year = this.d.getFullYear();
  
  this.containerId = (containerId !== null) ?  containerId: "calContainer";
  
  this.calElem = document.getElementById(this.containerId);
  
  this.id = 'id'; 
	}
	
  Kalender.prototype.toString = function()  {
		return "[object Kalendar]";
	}

  Kalender.prototype.getHandle = function(){
    return this;
  }

	Kalender.prototype.getDaysInMonth = function(month) {
	
	  if(month == undefined) {
	    month = this.month;
    }
    return new Date(this.year, month+1, 0).getDate();
   }

  Kalender.prototype.reset = function(date) {
    if(date == undefined) {
      date = this.d;
    }
    
  	this.day = date.getDate();
		this.month = date.getMonth();

		date.setDate(1);
		this.firstDay = date.getDay() - this.options.startDay;
		date.setDate(this.date);
    	this.year = date.getFullYear();
    this.d = 	date;
	}
	
	Kalender.prototype.hide = function() {
    if(document.getElementById("cal_" + this.containerId))
			document.getElementById("cal_" + this.containerId).style.display = "none";
  }
  
 	Kalender.prototype.show = function() {
  
   var doc = document;  
   if( window.handle && handle !== this) {
    handle.hide();
   }  
   handle = this;
   
   var monthsBuffer = [];
   var sbuffer = [];
   sbuffer.push('<div class="kalender" id="cal_' + this.containerId + '" onclick="handle.listener(event)">'); 
    
   var navigationBuffer = this.writeNavigation();
   for(var calIdx = 0; calIdx < this.options.calendars; calIdx++) {
    hasSelectbox = (this.options.monthSelector == 1 && calIdx == 0 && this.maxDate != this.DEFAULT_DATE && this.minDate != this.DEFAULT_DATE) ? true:false;
    if(calIdx > 0) { this.d.setMonth(this.d.getMonth() +1 ); }
    var activeMonth = this.cloneDate(this.d);

    this.d.setDate(1);
  	this.day = this.d.getDate();
		this.month = this.d.getMonth();
    this.firstDay = this.d.getDay();
	 	this.year = this.d.getFullYear();

    if(this.maxDate == this.DEFAULT_DATE || this.d - this.maxDate < 0) {    
      monthsBuffer.push(this.writeMonth (hasSelectbox)); 
    }
   }

    if(this.options.orientation.toLowerCase() != 'vertical') {
     monthsBuffer.push('<div style="clear:left"></div>'); 
    }  
   	
    if(this.options.navigationPosition.toLowerCase() == 'top') {
      sbuffer.push(navigationBuffer);
      sbuffer.push(monthsBuffer.join(''));
    } else {
      sbuffer.push(monthsBuffer.join(''));
      sbuffer.push(navigationBuffer);
    }	
     sbuffer.push('</div>'); 
   //resetting the date back.
    this.d.setMonth(this.d.getMonth() - (this.options.calendars - 1) );
    this.calElem.innerHTML = sbuffer.join('');
    
  }	
   
   Kalender.prototype.writeMonth = function(hasSelectbox) {
      var length = this.getDaysInMonth(this.month);
      var today = new Date();
      var doc = document;
      var sbuffer = [];
      
      if(this.options.orientation.toLowerCase() != 'vertical')
       sbuffer.push('<table cellpadding="0" cellspacing="0" class="month_container" style="float:left">');
      else
       sbuffer.push('<table cellpadding="0" cellspacing="0" class="month_container" >');
       sbuffer.push('<tr><th colspan="7" valign="top" class="month_name_container"><div class="month_name">' + this.months[this.month] + ' ' + this.year + '</div>');
        if(hasSelectbox) {
            sbuffer.push('<div>'+this.getSelectbox()+'</div>');
        }
      sbuffer.push('</th></tr>');
      sbuffer.push('<tr>');

      for( var i = 0 + this.options.startDay ; i < this.days.length + this.options.startDay; i++ )	{
       sbuffer.push('<th class="day_name">' + this.days[i%7] + '</th>');
      }
      sbuffer.push('</tr>');
        
      sbuffer.push('<tr>');
      var startValue = (7- this.options.startDay + this.firstDay) % 7 ;
      
      for(var j = 0; j < 42; j++ ) {
      
        var displayNum = j - startValue + 1;//(j - this.options.startDay + this.d.getDay());
        var dayNumber =  (displayNum + this.firstDay -1)% 7;
        var isLink = false;
        var isActive = false;
        var isWeekend = (dayNumber == 0  || dayNumber == 6) ? true:false;
        var isSelected = false;
        var isToday = false;
        
        if(displayNum > 0 && length >= displayNum) {
          var d = new Date(this.year, this.month, displayNum, 0, 0, 0);
          isLink = this.isLink(d);
          isActive = this.isActive(d);
          isSelected = this.isSelectedDate(d);
          isToday = this.isToday(d);
        }
        
        if( j  <  startValue  || displayNum > length) {
           var _d = this.cloneDate();
           _d.setDate(displayNum);
           
            if(_d.getDay() == 0 || _d.getDay() == 6 ) {
              sbuffer.push('<td class="weekend_disabled">' + _d.getDate() + '</td>');
            } else {
              sbuffer.push('<td class="date_disabled">' + _d.getDate() + '</td>');
            }  
        } 
        else if (isSelected) {
           sbuffer.push('<td class="date_active" id="'+this.id+'selected" date="' + displayNum+'.'+this.month+'.'+this.year +'">' + displayNum + '</td>');
        }
        else if ( (isToday && isLink && isActive) || (isLink && isActive) ) {
           if(isWeekend) {
            sbuffer.push('<td class="weekend_enabled" date="' + displayNum+'.'+this.month+'.'+this.year +'">' + displayNum + '</td>'); 
           } else {
            sbuffer.push('<td class="date_enabled" date="' + displayNum+'.'+this.month+'.'+this.year +'">' + displayNum + '</td>');
           }
        } else if (isLink && !isActive) {
           if(isWeekend) {
            sbuffer.push('<td class="weekend_inactive" >' + displayNum + '</td>'); 
           } else {
            sbuffer.push('<td class="date_inactive" >' + displayNum + '</td>');
           }
        } else  {
            if(isWeekend) { 
              sbuffer.push('<td class="weekend_disabled" >' + displayNum + '</td>');
            } else {
              sbuffer.push('<td class="date_disabled" >' + displayNum + '</td>');
            }  
        }
                
      if(j%7==6){
       sbuffer.push('</tr>');
       sbuffer.push('<tr>');
      }
      }
      
      sbuffer.push('</tr></table>');
      return sbuffer.join('');
   }
   
   Kalender.prototype.writeNavigation = function() {

    var sbuffer = [];
    sbuffer.push('<div class="navigation_container">');

    if(this.hasPreviousLink()) {
      sbuffer.push('<div class="back" id="back">' + this.previous_month + '</div>');
    } else {
      sbuffer.push('<div class="back_disabled" >' + this.previous_month + '</div>');
    }
    if(this.hasNextLink()) {
      sbuffer.push('<div class="next" id="next">' + this.next_month + '</div>');
    }else {
     sbuffer.push('<div class="next_disabled" >' + this.next_month + '</div>');
    }
     sbuffer.push('<div style="clear:both" ></div>');
     sbuffer.push('</div>');
    return sbuffer.join('');
   }
   
    Kalender.prototype.changeDate = function(td, date) {
  		var oDiv = document.getElementById(this.id + "selected");
  		
  		if(oDiv !== null) {
  		  oDiv.className = "days_link";
  		  oDiv.id = "";
  	  }
  		td.className =  "selected";
  		td.id = this.id + "selected";
  		this.date = parseInt(date);
  }
	
	Kalender.prototype.returnDate = function(month, year) {
		var selectedDate = new Date(year, month, this.date, 0, 0, 0);
    this.selectedDate = selectedDate;
		this.options['onSelect'](selectedDate);
		this.hide();
  }
	
  Kalender.prototype.changeMonth = function(mo) {
    
    this.d.setDate(1);
    this.d.setMonth(this.d.getMonth() + mo);
  	this.day = this.d.getDate();
		this.month = this.d.getMonth();
		this.firstDay = this.d.getDay() - this.options.startDay;
	 	this.year = this.d.getFullYear();
   
	  this.show(this);
	}

  Kalender.prototype.cloneDate = function(d) {
    var clone = new Date();
   	clone.setDate(this.date);
		clone.setMonth(this.month);
		clone.setYear(this.year);
		return clone;
  }
  
  Kalender.prototype.toDate = function(str) {
    if(str === undefined) {
      throw "Provided argument must not be null"; 
    }
    var dateArray = str.split(".");
    return new Date(dateArray[2], dateArray[1] - 1, dateArray[0], 0, 0, 0);
  }
  
  Kalender.prototype.isLink = function(d) {
    var response = false;
    if((this.maxDate == this.DEFAULT_DATE || this.maxDate >= d) && (this.minDate == this.DEFAULT_DATE || d >= this.minDate)) {
     response = true;
    }
    return response;
  }
  
  Kalender.prototype.isActive = function(d) {
     var response = false; 
     var dateList = this.options.dateList;
     if(dateList.length == 0 || (dateList.length >= 10 && dateList.indexOf(this.formate(d)) >= 0))
        response = true;
        
     return response;         
  }
  
  Kalender.prototype.isToday = function(d) {
    var response = false;
    var today = new Date();
    today.setHours(0);
    today.setMinutes(0);
    today.setSeconds(0);
    var diff = Math.round(( d - today ) / 86400000) // (86400000 = 1000*60*60*24) 

    if(diff  == 0) {
      response = true;
    }
    return response;
  }
  
  Kalender.prototype.isSelectedDate = function(d) {
    var response = false;
      if( this.selectedDate != '' && Math.round( d - this.selectedDate ) == 0 ) {
       response = true;
      }
    return response;
  }
  
  Kalender.prototype.hasNextLink = function() {
    var response = true;
    var maxMonth = parseInt(this.maxDate.getMonth());
    var maxYear = this.maxDate.getFullYear();
    var displayMonth = parseInt(this.d.getMonth() + this.options.calendars -1);
    var displayYear = this.d.getFullYear();

    if(displayMonth > 11) {
      displayMonth = displayMonth - 12;
      displayYear +=1; 
    }
     displayMonth = (displayMonth > 11) ? displayMonth - 12 : displayMonth
     
    if(this.maxDate != this.DEFAULT_DATE && maxMonth <= displayMonth && maxYear <= displayYear)
      response = false;
      
    return response; 
  }
  
  Kalender.prototype.hasPreviousLink = function() {
    var response = true;
    var _d = this.cloneDate();
    _d.setDate(1);  
   
    if(this.minDate != this.DEFAULT_DATE && _d  - this.minDate < 86400000)
      response = false;
      
    return response;  
  }
  
  Kalender.prototype.showMonth = function(month) {
    var response = true;
    if(parseInt(this.maxDate.getMonth()) < parseInt(month) && parseInt(this.d.getFullYear()) >= parseInt(this.maxDate.getFullYear()))
      response = false;
    return response;  
  }
  
  Kalender.prototype.getSelectbox = function() {
    var sbuffer = [];
    sbuffer.push('<select class="month_selectbox"  onchange="handle.redraw(this)">');
    var to = this.maxDate.getMonth() - this.minDate.getMonth() + (this.maxDate.getFullYear() - this.minDate.getFullYear())*12
    for( var i = 0; i <= to; i++) {
      var _d = new Date();
      _d.setFullYear(this.minDate.getFullYear());
      _d.setMonth(this.minDate.getMonth());
      
      if(i == 0) {
       // _d.setFullYear(this.minDate.getFullYear());
        _d.setDate(this.minDate.getDate());
      } else
         _d.setDate(1);
         
      _d.setMonth(this.minDate.getMonth()+i);
      
      var value = _d.getDate()+ "." + _d.getMonth()+ "." + _d.getFullYear();
      var option = this.months[_d.getMonth()] + " " + _d.getFullYear();
      if(_d.getMonth() == this.d.getMonth() && _d.getFullYear() == this.d.getFullYear())
        sbuffer.push('<option value = "'+ value +'" selected>' + option);
      else
        sbuffer.push('<option value = "'+ value +'">' + option);
    }
    return sbuffer.join('');
   }
  
  Kalender.prototype.redraw = function(refrence) {
    var selIndex = refrence.selectedIndex;
    var selvalue = refrence.options[selIndex].value;
    var selText = refrence.options[selIndex].text;
    if(selIndex + this.options.calendars + 1 > refrence.options.length) {
      var len = refrence.options.length;
      var idx = len - this.options.calendars ;
      selvalue = refrence.options[idx].value;
      this.d.setMonth(selvalue.split('.')[1]);
      this.d.setFullYear(selvalue.split('.')[2]);
    } else {
      this.d.setMonth(selvalue.split('.')[1]);
      this.d.setFullYear(selvalue.split('.')[2]);
    }
    this.show();
    
  }
  
  Kalender.prototype.addEvent = function(node, type, listener) {
    
    if(node.addEventListener) {
      node.addEventListener(type, listener, false);
      return true;
    } else if(node.attachEvent) {
      node['e'+type+listener] = listener;
      node[type+listener] = function() {
          node['e'+type+listener](window.event);
        }
      node.attachEvent('on'+type, node[type+listener]);
      
      return true;  
    }
    return false;
  }
  
  Kalender.prototype.listener = function(W3CEvent) {
    if(W3CEvent.srcElement) {
      var oTarget = W3CEvent.srcElement;
    } else {
      var oTarget = W3CEvent.target;
    }
    if(oTarget.id == 'next') {
      handle.changeMonth(1);
    } else if(oTarget.id == 'back') {
      handle.changeMonth(-1);
    } else if(oTarget.getAttribute('date')){
      var _date = oTarget.getAttribute('date');
      var _date_parts = _date.split('.');
      handle.changeDate(oTarget, _date_parts[0]);
      handle.returnDate(_date_parts[1] , _date_parts[2]);
    }
  }
  
  Kalender.prototype.formate = function(d) {
  
    if(d === undefined ||  !d instanceof Date) {
      throw "Provided argument should be a Date Object."; 
    }
    
    var date = (d.getDate() > 9) ? d.getDate():0+''+d.getDate();
	  var month = (d.getMonth() + 1 > 9)? parseInt(d.getMonth()+1) : 0 +''+ parseInt(d.getMonth()+1);
	  
	  return date + "." + month + "." + d.getFullYear();
  }
