if (typeof Date.prototype.getFullYear == "undefined") {
  Date.prototype.getFullYear = function() {
    var y = this.getYear();
    if (y < 1900) y += 1900;
    return y;
  };
}

Date.prototype.clone = function () {
  return new Date(this.getTime());
}

// BEGIN: DATE OBJECT PATCHES

/** Adds the number of days array to the Date object. */
Date._MD = new Array(31,28,31,30,31,30,31,31,30,31,30,31);

/** Constants used for time computations */
Date.SECOND = 1000 /* milliseconds */;
Date.MINUTE = 60 * Date.SECOND;
Date.HOUR   = 60 * Date.MINUTE;
Date.DAY    = 24 * Date.HOUR;
Date.WEEK   =  7 * Date.DAY;

/** Returns the number of days in the current month */
Date.prototype.getMonthDays = function(month) {
  var year = this.getFullYear();
  if (typeof month == "undefined") {
    month = this.getMonth();
  }
  if (((0 == (year%4)) && ( (0 != (year%100)) || (0 == (year%400)))) && month == 1) {
    return 29;
  } else {
    return Date._MD[month];
  }
};

/** Returns the number of day in the year. */
Date.prototype.getDayOfYear = function() {
  var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
  var then = new Date(this.getFullYear(), 0, 0, 0, 0, 0);
  var time = now - then;
  return Math.floor(time / Date.DAY);
};

/** Returns the number of the week in year, as defined in ISO 8601. */
Date.prototype.getWeekNumber = function() {
  var d = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
  var DoW = d.getDay();
  d.setDate(d.getDate() - (DoW) % 7 + 3); // Nearest Thu
  var ms = d.valueOf(); // GMT
  d.setMonth(0);
  d.setDate(4); // Thu in Week 1
  return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1;
};

if(typeof VYRE === "undefined") {
    VYRE = {
        name:"VYRE"
    };
}

VYRE.Calendar = function (settings) {
    this.container = null;
    this.title="put title here";
    this.nextText="»";
    this.previousText="«";
    this.shiftOnInactive = false;
    if( typeof settings != "undefined" ) {
        for( var property in this) {
            if(typeof settings[property] != "undefined") {
                this[property] = settings[property];
            }
        }
    }
    this.clickHandler = function () {};
    this.callBackFunction = function () {};
    this.date = new Date();
    this.date.setDate(1);
};

VYRE.Calendar.months = localisedMonths;
VYRE.Calendar.days =  localisedDays;


VYRE.Calendar.prototype = {
    
    init : function (){
        var self = this;
        this.makeCalendar();
        this.clickHandler(this.date);
    },
    
    getFirstDay : function () {;
        startDate = new Date();
        startDate.setFullYear(this.date.getFullYear(),this.date.getMonth(),1);
        startDate.setDate(1);
        var firstDay = startDate.getDay();
        //if(firstDay == 0) {firstDay = 7;}
        
        
        firstDay = (firstDay > 7) ? (firstDay % 7) : firstDay;
        
        return firstDay;
    }, 
    
    makeCalendar : function () {
    var self = this;
    
    var startDay = this.getFirstDay()+1;
    var daysInMonth = this.date.getMonthDays();
    var month = this.date.getMonth();
    var year = this.date.getFullYear();
    var endLoop = (Math.ceil((startDay + daysInMonth -1 )/7))*7;
    var today = new Date();
    
    var previousMonth = new Date();
    previousMonth.setDate(1);
    previousMonth.setMonth(this.date.getMonth()-1);
    previousMonthYear = previousMonth.getFullYear();
    previousMonthDays = previousMonth.getMonthDays();
    
    str="<h2><span>{title}</span></h2><div class='container'><div class='inner'>".supplant({title:this.title});
    str += "<h3><span id ='calNext'>{nextText}</span><span id ='calPrev'>{previousText}</span><span class = 'monthYear'>{month} {year}</span></h3>".supplant({month:VYRE.Calendar.months[month],year:year, previousText:this.previousText, nextText:this.nextText});
    str+="<table id=\"calendar\" border ='0' cellspacing ='0' cellpadding ='0'><thead><tr><th class=\"first\"><span>{sun}</span></th><th><span>{mon}</span></th><th><span>{tue}</span></th><th><span>{wed}</span></th><th><span>{thu}</span></th><th><span>{fri}</span></th><th class=\"last\"><span>{sat}</span></th></tr></thead><tbody>".supplant(VYRE.Calendar.days);
    for(var i = 1;i<=endLoop; i++ ) {
      var mod = i % 7;
      if(mod == 1) {
        if(i<7) {
          str+="<tr class=\"first\">";
        } else if((i +7)>=endLoop){
          str+="<tr class=\"last\">";
        } else {
          str+="<tr>";
        }
      }
      var day1 = i-startDay +1 ;
      var extraClass=" d"+i%2;  
      
      var dayText = "<span>{day}</span>".supplant({day:day1});
      if(today.getFullYear() == year && today.getMonth() == month && day1 == today.getDate()) {
        extraClass+=" today";
      }
      if(mod == 1){ extraClass += " first";}
      if(mod == 0){ extraClass += " last";}

      if(i < startDay) {
        var previousMonthDay =previousMonthDays -( startDay - i-1);
        var previousMonthDayText = "<span>{day}</span>".supplant({day:previousMonthDay});
        str += "<td id ='td{year}{month}{day}' class ='inactive{extraClass}'>{dayText}</td>".supplant({day:previousMonthDay,dayText:previousMonthDayText,extraClass:extraClass, month:previousMonth.getMonth(), year:previousMonthYear});
      } else if(day1 > daysInMonth){
        var nextMonthDay = day1 - daysInMonth;
        var nextMonthDayText = "<span>{day}</span>".supplant({day:nextMonthDay});
        var nextMonthYear = (month == 11)? year +1: year;
        str += "<td id ='td{year}{month}{day}' class ='inactive{extraClass}'>{dayText}</td>".supplant({day:nextMonthDay,dayText:nextMonthDayText,extraClass:extraClass, month:(month ==11)? 0 : month +1, year:nextMonthYear});   
      } else {
        str += "<td id ='td{year}{month}{day}' class ='active{extraClass}'>{dayText}</td>".supplant({day:day1,dayText:dayText,extraClass:extraClass, month:month, year:year});
      }
      if(mod == 0) {
        str+="</tr>";
      }
    }
    str+="</tbody></table></div><div class=\"clearer\"></div></div>";
    this.container.innerHTML = str;

    VYRE.Utils.gE("calPrev").onclick = function () {
      self.previous();
      self.clickHandler(self.date);
    };
    VYRE.Utils.gE("calNext").onclick = function () {
      self.next();
      self.clickHandler(self.date);
    };
    VYRE.Utils.gE("calendar").onmousedown= function (e) {
      var e = e || event;
      var targ = e.target || e.srcElement;
      var element = null;
      var clickedDate = self.date.clone();
      if(targ.nodeName=="TD") {
        element = targ.childNodes[0];
      } else if(targ.nodeName=="SPAN"){
        element = targ
      }

      if(element){
        var day = element.innerHTML;
        if(element.parentNode.className.indexOf("inactive") != -1){
          if(day <10) {
            clickedDate.setMonth(clickedDate.getMonth()+1);
          } else {
            clickedDate.setMonth(clickedDate.getMonth()-1);
          }
          if(self.shiftOnInactive) {
            self.date = clickedDate
            self.makeCalendar();
          }
        }
        
        if(day > 0) {
          clickedDate.setDate(day);
          //self.clickHandler(clickedDate);
        }
      }

    };    
    this.callBackFunction();
    },
    keepDoubleDigit : function (number) {
        if(parseInt(number) <10) {number = "0"+number;}
        return number;
    },
    next : function () {
    this.date.setMonth(this.date.getMonth()+1);
    this.makeCalendar();
    },
    
    previous : function () {
    this.date.setMonth(this.date.getMonth()-1);
    this.makeCalendar();
    }
    
};



VYRE.CalendarSearch = function (settings) {
  this.calendar = null;
  this.ajaxSearch = null;
  this.dayOffset = 0;
  this.additionalDays = 0;
  this.lucenePrefix = null;
    if( typeof settings != "undefined" ) {
        for( var property in this) {
            if(typeof settings[property] != "undefined") {
                this[property] = settings[property];
            }
        }
    }
    this.currentDate = new Date();
  this.init();
};

VYRE.CalendarSearch.prototype = {
  init : function () {
    var self = this;

    
    this.calendar.clickHandler = function (date) {
      self.click(date);
    }
    this.calendar.callBackFunction = function () {
      self.highlightDays();
    }
    this.click(this.currentDate);
  },
  
  click : function (date) {
    if(this.ajaxSearch.canSearch == true) {
      this.currentDate = date.clone();
      var vyreDate = new VYRE.Date();
      vyreDate.setJSDate(date.clone());
      vyreDate.addDays(this.dayOffset);
      var vyreDate2 = new VYRE.Date();
      vyreDate2.setJSDate(date.clone());
      vyreDate2.addDays(this.calendar.date.getMonthDays() + this.dayOffset);
      var luceneDate="["+vyreDate.getLuceneString().substring(0,6)+"01" +"000000 TO "+vyreDate2.getLuceneString().substring(0,6)+"01"+"000000]";
      this.ajaxSearch.attributes.set(new VYRE.Attribute(this.lucenePrefix,luceneDate));
      this.ajaxSearch.search(); 
      this.highlightDays();  
    }   
  }, 
  generateArrows : function () {
    var self = this;
    if(!(VYRE.Utils.gE("prevM") && VYRE.Utils.gE("nextM"))) {
      this.spanPrev = VYRE.Utils.createElement({tag:"span",id:"prevM", innerText:this.calendar.previousText});
      this.spanPrev.style.display="none";
      this.spanNext = VYRE.Utils.createElement({tag:"span",id:"nextM", innerText:this.calendar.nextText});
      this.spanNext.style.display="none";
      //this.calendar.container.appendChild(this.spanPrev);
      //this.calendar.container.appendChild(this.spanNext);
      $("#calendarWidget .inner table").before(this.spanPrev).after(this.spanNext);
    }

    this.spanPrev.onclick = function () {
      self.calendar.previous();
    }

    this.spanNext.onclick = function () {
      self.calendar.next();
    }
  
  },
  highlightDays : function () {
  

    this.generateArrows();
  
    var dateAcc = this.currentDate.clone();
    dateAcc.setDate(1+this.dayOffset);
    $("#calendarWidget td").removeClass("current").removeClass("selected").removeClass("start").removeClass("end");
    
    var dateExists = false;
    var previousExists = false;
    var nextExists = false;
    for(var i = this.dayOffset; i<= (this.calendar.date.getMonthDays()+this.dayOffset); i++) {
      var  d = dateAcc.getDate();
      var  m = dateAcc.getMonth();
      var ye = dateAcc.getFullYear();
      var dateId = "#td"+ye+m+d;
      if(typeof $(dateId)[0] != "undefined") {
        dateExists = true;
        if(i==this.dayOffset) {
          previousExists = true;
        }
        if(i==(this.additionalDays+this.dayOffset)) {
          nextExists = true;
        }
      } 
      $(dateId).addClass("selected");
      if(i == this.dayOffset) {
        $(dateId).addClass("start");  
      }
      if(i == 0) {
        $(dateId).addClass("current");          
      }
      if(i == (this.additionalDays+this.dayOffset)) {
        $(dateId).addClass("end");  
      }
      dateAcc.setDate(dateAcc.getDate()+1);
    }   
    
    if(dateExists == true) {
      this.spanPrev.style.display = (previousExists)? "none" : "block";
      this.spanNext.style.display = (nextExists)? "none" : "block";
    } else {
      this.spanPrev.style.display = "none";
      this.spanNext.style.display = "none";     
    }
  }
};
