/*******************************************************************************
 * Copyright (c) 2008 Wotif.com Holdings Ltd. All Rights Reserved.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 ******************************************************************************/

// DatePicker 20071012. Allan Fok.

var DatePicker = new Class ({
  stopev: function(ev) {
    new Event(ev).stop();
  },
  
  initialize: function(inputBox, numMonths) {
    this.numMonths = numMonths;
    this.active = false;
    this.inputBox = $(inputBox);
    this.months = [
      'January',
      'February',
      'March',
      'April',
      'May',
      'June',
      'July',
      'August',
      'September',
      'October',
      'November',
      'December'];
    this.days = ['M','T','W','T','F','S','S'];
    this.daysOfWeek = ['Mon','Tue','Wed','Thur','Fri','Sat','Sun'];
    this.daysPerMonth = [31,28,31,30,31,30,31,31,30,31,30,31];

    this.today = new Date();
    this.today.setHours(0);
    this.today.setMinutes(0);
    this.today.setSeconds(0);
    this.today.setMilliseconds(0);
    
    this.d = this.today.getDate();
    this.m = this.today.getMonth()+1;
    this.y = this.today.getFullYear();
    
    this.showm = this.m;
    this.showy = this.y;

    /* add day of week display */
    if (this.inputBox.hasClass('dp-showdow')) {
      this.dayOfWeekDisp = new Element('span',{'class':'dp-dayofweek'}).injectBefore(inputBox);
      this.inputchange();
    }

    /* add side button */
    this.button = new Element('button',{'class':'dp-btn'}).injectAfter(inputBox);
    this.button.addEvent('mousedown', (function(e) {
      this.setdate(this.inputBox.value);
      this.show();
    }).bind(this));    
    this.button.addEvent('click', this.stopev);
    
    /* input box */
    this.inputBox.setProperty('autocomplete', 'off');
    if (this.inputBox.getValue() == '') {
      this.inputBox.value = 'dd/mm/yyyy';
    }    
    this.inputBox.addEvent('mousedown', (function(e) {
      if (this.inputBox.value == 'dd/mm/yyyy') {
        this.inputBox.value = '';
      }      
      this.setdate(this.inputBox.value);
      this.inputBox.focus();
      this.show();
    }).bind(this));
    this.inputBox.addEvent('keyup', (function(e) {
      this.inputchange();
    }).bind(this));
    this.inputBox.addEvent('blur', (function(e) {
      if (this.inputBox.value == '') {
        this.inputBox.value = 'dd/mm/yyyy';
      }
      //this.hide();
    }).bind(this));
    this.inputBox.addEvent('keypress', (function(e) {
      this.hide();
      e = new Event(e);
      if (e.code == 47) return true;  // slash character
      if (e.key.match(/delete|backspace|left|right|tab|\d/)) return true;
      
      e.stop();
    }).bind(this));
    this.inputBox.addEvent('change', (function(e) {
      this.inputchange();
    }).bind(this));
    
    this.limit = this.today.getTime() + (365 * 24 * 60 * 60 * 1000);
    
    /* hide cal when user clicks anywhere on doc */
    document.addEvent('mousedown', (function(e) {
      var e = new Event(e);
      if (e.target == this.inputBox || e.target == this.button || e.target == this.nextbtn || e.target == this.prevbtn) {
        return;
      }
      this.hide();
    }).bind(this));
    
    this.outercontainer = new Element('div',{'class':'dp-container'}).injectBefore(inputBox);
    this.container = new Element('div', {'class':'dp','styles':{'opacity':0}}).injectInside(this.outercontainer);
    
    if (window.gecko) {
      this.outercontainer.setStyle('top', 3); 
    } else {
      this.outercontainer.setStyle('top', this.inputBox.getSize()['size']['y'] - 1);
    }
    
    this.container.addEvent('mousedown', function(e) {
      new Event(e).stop();
    });
    
    /* ie hack - iframe to protect from select boxes covering calendar */    
    if (window.ie) {
      this.iframe = new Element('iframe',{'class':'ie','styles':{'display':'none'}}).injectInside(this.outercontainer);
    }

  },
  
  /* corrects month/year combo e.g. 15/2007 -> 3/2008 */
  correctmonth: function(month,year) {
    if (month>12) {
      year += (month - (month % 12)) / 12;
      month = month % 12;
    }
    return [month,year];
  },
  
  setdate: function(value) {
    if (this.prevvalue == value) return;
    
    this.prevvalue = value;
      
    var values = value.split('/');
    var d = values[0];
    var m = values[1];
    var y = values[2];
    
    var date = new Date(y, m-1, d);
    if (date.getTime()<this.today.getTime() || isNaN(date)) {
      date = this.today;
    }
    
    this.d = date.getDate();
    this.m = date.getMonth() + 1;
    this.y = date.getFullYear();
    
    /* keeps relative position of months box */
    var result = this.correctmonth(this.showm+this.numMonths-1, this.showy);
    if (!(new Date(this.showy,this.showm-1,1).getTime()<=date.getTime() && date.getTime()<=new Date(result[1],result[0]-1,this.daysPerMonth[result[0]-1]).getTime())) {
      this.showm = this.m;
      this.showy = this.y;
    }
    
    this.draw(this.numMonths);
  },
  
  show: function() {
    if (this.active) return; 
  
    this.active = true;
    (new Fx.Style(this.container, 'opacity', {duration:500})).start(0.85);
    
    if (this.iframe) {
      this.iframe.style.width = this.container.getSize()['size']['x'] + "px";
      this.iframe.style.height = this.container.getSize()['size']['y'] + "px";
      this.iframe.setStyle('display','block');
    }
  },
  
  hide: function() {
    this.active = false;
    (new Fx.Style(this.container, 'opacity', {duration:500})).set(0);
    
    if (this.iframe) this.iframe.setStyle('display','none');
  },
  
  datehover: function(ev) {
    new Event(ev).target.addClass('hover');
  },
  
  dateunhover: function(ev) {
    new Event(ev).target.removeClass('hover');
  },
  
  inputchange: function() {
    if (this.dayOfWeekDisp == null) return;
    this.dayOfWeekDisp.setHTML('');
    
    var value = this.inputBox.value;
    if (value != '') {
      var values = value.split('/');
      var d = values[0];
      var m = values[1];
      var y = values[2];
            
      var date = new Date(y, m - 1, d);
      if (isNaN(date) || d == '' || m == '' || y == '') return;
      
      var day = date.getDay() == 0 ? 6 : date.getDay() - 1;
      this.dayOfWeekDisp.setHTML(this.daysOfWeek[day]);
    }
  },
  
  dateselect: function(ev) {
    var ev = new Event(ev);
    ev.stop();
    
    if (this.selected != null) {
      this.selected.removeClass('selected');
    }
    this.selected = ev.target;
    
    ev.target.addClass('selected');
    
    var datestr = ev.target.getProperty('title').split(' ');
    if (this.dayOfWeekDisp != null)
      this.dayOfWeekDisp.setHTML(datestr[0]);
  
    this.inputBox.value = datestr[1];
    this.inputBox.fireEvent('change');
    this.hide();  
  },
  
  prev: function(ev) {
    new Event(ev).stop();            
    this.showm -= this.numMonths;
    if (this.showm <= 0) {
      this.showm = this.showm + 12;
      this.showy--;
    }
    this.draw(this.numMonths);  
  },
  
  next: function(ev) {
    new Event(ev).stop();
    this.showm += this.numMonths;
    if (this.showm > 12) {
      this.showm = this.showm - 12;
      this.showy++;            
    }
    this.draw(this.numMonths);
  },
  
  draw: function(numMonths) {
    var d = this.d;
    var m = this.showm;
    var y = this.showy;
    
    $ES('div.month', this.container).each(function(div) {
      div.setStyle('display','none');
    });
    
    for (i=0;i<numMonths;i++) {
      /* check if it has been drawn previously */
      var div = $E('div.' + m + '-' + y, this.container);
      if (div) {
        div.setStyle('display','block');
        $E('.prev-btn', div).setStyle('display', 'none');
        $E('.next-btn', div).setStyle('display', 'none');
        if (i==0) $E('.prev-btn', div).setStyle('display','inline');    
        if (i==numMonths-1) $E('.next-btn', div).setStyle('display','inline');    
        
      } else {    
        
        var div = new Element('div', {'class':'month ' + m + '-' + y}).injectInside(this.container);
        var monthdesc = new Element('div',{'class':'desc'}).injectInside(div);        
        
        /* prev button */
        var prevbtn = this.prevbtn = new Element('button',{'class':'prev-btn','styles':{'display':'none'}});
        prevbtn.addEvent('mousedown', (this.prev).bind(this));
        prevbtn.addEvent('click', this.stopev);
        if (i==0) {
          prevbtn.setStyle('display','inline');
        }
        
        /* next button */
        var nextbtn = this.nextbtn = new Element('button',{'class':'next-btn','styles':{'display':'none'}});
        nextbtn.addEvent('mousedown', (this.next).bind(this));
        nextbtn.addEvent('click', this.stopev);
        if (i==numMonths-1) {
          nextbtn.setStyle('display','inline');
        }

        prevbtn.injectInside(monthdesc);
        nextbtn.injectInside(monthdesc);
        monthdesc.appendText(this.months[m-1] + ' ' + y);
        
        var month = new Element('ul').injectInside(div);
        /* draw days of week */
        this.days.each(function(day, index) {
          var dow = new Element('li',{'class':'dow'}).setHTML(day).injectInside(month);
          if (index==0) dow.setStyle('clear','left');
        });
        
        /* check for leap year */
        var days = this.daysPerMonth[m-1];
        if (((0 == (y%4)) && ((0 != (y%100)) || (0 == (y%400)))) && m == 2) {
          days = 29;
        };
        
        /* calculate offset */
        var date = new Date(y,m-1,1);
        date.setHours(0);
        date.setMinutes(0);
        date.setSeconds(0);
        date.setMilliseconds(0);

        offset = date.getDay() - 1;
        if (offset == -1) offset=6;
        j=7;
        rows=0;
        todaytime = this.today.getTime();
        datetime = date.getTime();
        for (day=1-offset;day<=days;day++) {
          e = new Element('li').setHTML((day>0) ? day : '').injectInside(month);
          if (day>0) {
            e.setProperty('title', this.daysOfWeek[j] + ' ' + day + '/' + m + '/' + y);
            if (day==this.d&&m==this.m&&y==this.y) {
              e.addClass('selected');
              this.selected = e;
            }
            if (datetime<todaytime || datetime >= this.limit) {
              e.addClass('past');
            } else {
              e.addEvent('mouseover', (this.datehover).bind(this));
              e.addEvent('mouseout', (this.dateunhover).bind(this));
              e.addEvent('mousedown', (this.dateselect).bind(this));
            }
          } else {
            e.addClass('noday');
          }
          
          
          if (j==7) {
            j=0;
            rows++;
            e.setStyle('clear','left');
          }
          j++;
          
          if (day>0)
            datetime += 24 * 60 * 60 * 1000;
        }
        for (j=rows;j<6;j++) {
          e = new Element('li').injectInside(month).setStyle('clear','left');
        }
      }
      
      m++;
      if (m==13) {
        m=1;
        y++;
      }
    }
  }
});

window.addEvent('domready', function() {
  $$('input.datepicker').each(function(inputBox) {
    new DatePicker(inputBox, 2);
  });
});