JALHotels.Calendar.settings = function(classPrefix, dateFormat, minDate, maxDate) {
  // dateFormat : accepted values 'yy/mm/dd' or 'yy/m/d'
  var self = this;
  this.holidays = JALHotels.Calendar.holidays;
  this.classPrefix = classPrefix;
  this.dateFormat = dateFormat;
  this.minDate = minDate;
  this.maxDate = maxDate;
  this.showOn = 'button';
  this.buttonImage = '/shared/img/stay/icon_calendar01.gif'; // カレンダーアイコンパス
  this.buttonImageOnly = true;
  this.buttonText = 'カレンダー';
  this.numberOfMonths = 1;
  this.duration = '';
  this.showButtonPanel = true;
  this.onSelect = function(date) {
    var f = $(this.form);
    // assume date format as either yy/mm/dd(2009/01/01) or yy/m/d(2009/1/1)
    // so we use the slash(/) to split the values
    $('.' + self.classPrefix + 'Year', f).val(date.split('/')[0]);
    $('.' + self.classPrefix + 'Month', f).val(date.split('/')[1]);
    $('.' + self.classPrefix + 'Day', f).val(date.split('/')[2]).trigger('change');
  };
  this.beforeShow = function() {
    var f = $(this.form);
    var now = new Date();
    var year =  $('.' + self.classPrefix + 'Year', f).val();
    if (year == undefined) { //DP rez module does not have hidden year values
      var year = now.getFullYear();
    }
    var month = $('.' + self.classPrefix + 'Month', f).val();
    var day =   $('.' + self.classPrefix + 'Day', f).val();
    var selectedDate = new Date(year, (month - 1), day, 23, 59, 59); // Dom rez defaults to today
    if (selectedDate.getTime() < now.getTime()) {
      selectedDate.setFullYear(now.getFullYear() + 1);
    }
    var formatedDate = $.datepicker.formatDate(self.dateFormat, selectedDate);
    $(this).val(formatedDate);  
  };
}

JALHotels.Calendar.nThDayOfMonth = function(nth, day, month, year) {
  var firstDate = new Date(year, month, 1);
  var dayModif = 6 - day;
  var date = nth * 7 - (firstDate.getDay() + dayModif) % 7;
  return new Date(year, month, date);
}

JALHotels.Calendar.japaneseHolidays = function(year){
  var h = [];  // all holidays
  var hi = []; // holiday index - to find holiday existence
  var th = []; // transfer holidays
  var verDay = parseInt(0.24242 * year - parseInt(year / 4) + 35.84, 10);
  var autDay = parseInt(0.24204 * year - parseInt(year / 4) + 39.01, 10);

  h.push(new Date(year, 0, 1));         // New Year's Day - Jan 1
  h.push(JALHotels.Calendar.nThDayOfMonth(2, 1, 0, year)); // Seijin no hi - 2nd Mon of Jan
  h.push(new Date(year, 1, 11));        // Kenkoku kinen no hi - Feb 11
  h.push(new Date(year, 2, verDay));    // Vernal equinox - Around Mar 20
  h.push(new Date(year, 3, 29));        // Showa no hi - Apr 29
  h.push(new Date(year, 4, 3));         // GW: Kenpo kinenbi - May 3
  h.push(new Date(year, 4, 4));         // GW: Midori no hi - May 4
  h.push(new Date(year, 4, 5));         // GW: Kodomo no hi - May 5
  h.push(JALHotels.Calendar.nThDayOfMonth(3, 1, 6, year)); // Umi no hi - 3rd Mon of Jul
  h.push(JALHotels.Calendar.nThDayOfMonth(3, 1, 8, year)); // Keiro no hi - 3rd Mon of Sep
  h.push(new Date(year, 8, autDay));    // Autumnal equinox - Around Sep 23
  h.push(JALHotels.Calendar.nThDayOfMonth(2, 1, 9, year)); // Taiiku no hi - 2nd Mon of Oct
  h.push(new Date(year, 10, 3));        // Bunka no hi - Nov 3
  h.push(new Date(year, 10, 23));       // Kinro kansha no hi - Nov 23
  h.push(new Date(year, 11, 23));       // Tenno tanjobi - Dec 23

  for(var x = 0; x < h.length; x++) {
    if (h[x].getDay() == 0) { // Sun holidays are transfer holidays
      th.push(h[x].getTime());
    }
    h[x] = h[x].getTime();
    hi[h[x]] = true;
  }
  // transfer holidays - Sun holidays are transferred to the next non-holiday date
  for(var x = 0; x < th.length; x++) {
    var nextDay = th[x] + (60 * 60 * 24 * 1000);
    while(hi[nextDay]) {
      nextDay = nextDay + (60 * 60 * 24 * 1000);
    }
    h.push(nextDay);
  }
  // between holidays
  for(var x = 0; x < h.length; x++) {
    var hDay = new Date(h[x]);
    var nextDay = h[x] + (60 * 60 * 24 * 1000);
    var nextNextDay = h[x] + ((60 * 60 * 24 * 1000) * 2);
    if ((hDay.getDay() != 0) && // NOT Sun
        (! hi[nextDay]) &&      // next day is NOT holiday
        (hi[nextNextDay])) {    // next next day IS holiday
      h.push(nextDay);
    }
  }
  return h;
}

JALHotels.Calendar.factory = function(calId, calClass, calSettings) {
  var checkIn  = new calClass.settings(
    'ci',
    calSettings.format,
    calSettings.start,
    calSettings.end
  );
  var checkOut = new calClass.settings(
    'co',
    calSettings.format,
    calSettings.start,
    calSettings.end
  );
  $("#" + calId + "CheckInCal").datepicker(checkIn);
  $("#" + calId + "CheckOutCal").datepicker(checkOut);
}

JALHotels.Calendar.now = new Date();
JALHotels.Calendar.thisYear = JALHotels.Calendar.now.getFullYear();

// domestic dates
// format: 2009/01/01
// range: today until the end of next year
JALHotels.Calendar.domDates = {};
JALHotels.Calendar.domDates.format = 'yy/mm/dd';
JALHotels.Calendar.domDates.start ='+0';
JALHotels.Calendar.domDates.end = new Date(JALHotels.Calendar.thisYear + 1, 11, 31);

// dynamic package dates
// format: 2009/1/1
// range: ten days from now, until one year from today
JALHotels.Calendar.dpDates = {};
JALHotels.Calendar.dpDates.format = 'yy/m/d';
JALHotels.Calendar.dpDates.start ='+10';
JALHotels.Calendar.dpDates.end = '+365';

// international dates
// format: 2009/1/1
// range: today until the end of next year
JALHotels.Calendar.intDates = {};
JALHotels.Calendar.intDates.format = 'yy/m/d';
JALHotels.Calendar.intDates.start ='+0';
JALHotels.Calendar.intDates.end = new Date(JALHotels.Calendar.thisYear + 1, 11, 31);

// holiday range
JALHotels.Calendar.holidayStart = JALHotels.Calendar.thisYear;
JALHotels.Calendar.holidayEnd   = JALHotels.Calendar.thisYear + 2;
JALHotels.Calendar.holidays = JALHotels.Calendar.japaneseHolidays(JALHotels.Calendar.holidayStart);
for (var year = JALHotels.Calendar.holidayStart + 1; year <= JALHotels.Calendar.holidayEnd; year ++) {
  JALHotels.Calendar.holidays = JALHotels.Calendar.holidays.concat(JALHotels.Calendar.japaneseHolidays(year));
}
