// ------------------------------------------------- Date Validation ------------------------------------------------//
// month names array
var months = new Array("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
// regular expressions:
var n_days = "(\\d{2})";
var s_mons = "((Jan(uary)?)|(Feb(ruary)?)|(Mar(ch)?)|(Apr(il)?)|(May)|(Jun(e)?)|(Jul(y)?)|(Aug(ust)?)|(Sep(tember)?)|(Oct(ober)?)|(Nov(ember)?)|(Dec(ember)?))";
var n_mons = "(\\d{2})";
var n_yers = "(\\d{2}|\\d{4})";
var s_delm = "([\\:\\-\\/\\s])?";
var s_date = "^" + n_days + s_delm + "(" + s_mons + "|" + n_mons + ")" + s_delm + n_yers + "$";
var s_ddmm = "^" + n_days + s_delm + "(" + s_mons + "|" + n_mons + ")" + s_delm + "$";

// RegExp Objects used to validate date
var re_date = new RegExp(s_date, "i");
var re_ddmm = new RegExp(s_ddmm, "i");
var re_delm = new RegExp(s_delm, "g");
// baseyear to handle 2 digit years
// all years less than baseyear is assumed to be in 20th century, otherwise 19th.
var baseyear = 70;
/*
 *  function parseM4Date(str_date)
 *  Description:
 *    This function takes a String parameter to be validated as date. Allowed 
 *    date formats are (any combination of delimiters can be used):
 *      ddmmyy
 *      ddmmyyyy
 *      ddmonyy
 *      ddmonyyyy
 *      ddmonthyy
 *      ddmonthyyy
 *      dd-mm-yy
 *      dd-mm-yyyy
 *      dd-mon-yy
 *      dd-mon-yyyy
 *      dd-month-yy
 *      dd-month-yyyy
 *      dd/mm/yy
 *      dd/mm/yyyy
 *      dd/mon/yy
 *      dd/month/yyyy
 *    If 2 digit year is specified, baseyear is used to determine century.
 *
 *  Parameter(s):
 *    str_date: String - string to be validated as date.
 *
 *  Return value:
 *    If the string is a valid date, the function returns a date object.
 */
function parseM4Date(str_date) {
  // if no argumants then return null
  if (parseM4Date.arguments.length == 0) {
    return null;
  }
  // search for date pattern (day-month-year)
  if (str_date.search(re_date) == 0) {
    var d, m, y;
    // separate day, month and year
    re_date.exec(str_date);
    d = RegExp.$1;
    m = RegExp.$3;
    y = str_date.replace(/[\:\-\/\s]/ig, "").substr((d+m).length);
    // get month#-1
    if (isNaN(m)) {
      var i;
      m = m.substr(0, 3);
      for (i=0; i<months.length; i++)
        if (months[i].toLowerCase() == m.toLowerCase()) break;
      m = i;
    } else {
      m--;
    }
    // convert year to 4 digit
    y = (y.length == 2) ? ((y < baseyear) ? ("20"+y) : ("19"+y)) : y;
    // create a date object to verify the date
    var date = new Date(y, m, d);
    //alert("GMT: " + date.toGMTString() + "\nLocale: " + date.toLocaleString() + "\nUTC: " + date.toUTCString());
    if ((date.getDate() == d) && (date.getMonth() == m) && (date.getFullYear() == y)) {
      return date;
    }
  }
  // search for date pattern (day-month)
  else if (str_date.search(re_ddmm) == 0) {
    var d, m, y;
    // separate day, month and year
    re_date.exec(str_date);
    d = RegExp.$1;
    m = RegExp.$3;
    var today = new Date();
    y = today.getFullYear();
    // get month#-1
    if (isNaN(m)) {
      var i;
      m = m.substr(0, 3);
      for (i=0; i<months.length; i++)
        if (months[i].toLowerCase() == m.toLowerCase()) break;
      m = i;
    } else {
      m--;
    }
    // convert year to 4 digit
    y = (y.length == 2) ? ((y < baseyear) ? ("20"+y) : ("19"+y)) : y;
    // if less that current date then set to next year
    if ((m < today.getMonth()) || (m == today.getMonth() && d < today.getDate()))
      y++;
    // create a date object to verify the date
    var date = new Date(y, m, d);
    //alert("GMT: " + date.toGMTString() + "\nLocale: " + date.toLocaleString() + "\nUTC: " + date.toUTCString());
    if ((date.getDate() == d) && (date.getMonth() == m) && (date.getFullYear() == y)) {
      return date;
    }
  }
  return null;
}
/*
 *  function allowDate(element)
 *  Description:
 *    This function is an event handler to validate user input as date. It sets the 
 *    'value' property of the 'element' to the dd-mon-yyyy (e.g. 11-Nov-1974). Example:
 *      <input type="text" id="txtDate" name="txtDate" onblur="allowDate(this)">
 *
 *  FTA 010725 - allowDate(element, length)
 *    With length parameter it will set 'value' property of the 'element' to different
 *    date format (D04-D29). Allowed values for length is between 4 to 29. e.g.
 *    <input type="text" id="txtDate" name="txtDate" onfocus="allowDate(this, 6); this.select();" onblur="allowDate(this)">
 *    will set date to D06 and select the text in focus in and D11 on focus out.
 *
 *  Parameter(s):
 *    element: Scriptable HTML form element that has a value property. The 'value'
 *             property will be validated as date.
 *
 *  Return value:
 *    true for a valid date, false otherwise.
 *
 */
function allowDate(element, length) {
  // if no arguments return false
  if (allowDate.arguments.length == 0) {
    return false;
  }
  // does the element has a value property?
  if (typeof(element.value) == "undefined") {
    return false;
  }
  // blank accepted
  if (element.value == "") {
    return true;
  }
  // the real work
  var date = parseM4Date(element.value);
  if (date == null)
 {
    element.value = ""; // clear
    alert("Invalid Date");
    return false;
  }
/* OLD style - only D11 output
  var d = date.getDate();
  d = (d<10) ? ("0"+d) : d;
  var y = date.getFullYear();
  y = (y<10) ? ("0"+y) : y;
  y = (y<100) ? ("0"+y) : y;
  y = (y<1000) ? ("0"+y) : y;
  element.value =  d + "-" + months[date.getMonth()] + "-" + y;
*/
  if (typeof(length) == "undefined") {
    element.value =  formatDate(date, 11); // default D11
  }
  else {
    if ((length < 4) || (length > 29)) length = 11;
    element.value =  formatDate(date, length);
  }
  return true;
}

var l_days = new Array(
  'Sunday', 'Monday', 'Tuesday', 'Wednesday', 
  'Thursday', 'Friday', 'Saturday'
  );
var l_months = new Array(
  'January', 'February', 'March', 'April', 'May', 'June', 
  'July', 'August', 'September', 'October', 'November', 'December'
  );
var d_formats = new Array(
  'DDMM', 'DD-MM', 'DDMMYY', 'DDMMMYY', /* 4, 5, 6, 7 */
  'DD-MM-YY', 'DD-MMM-YY', 'DD-MM-YYYY', 'DD-MMM-YYYY', /* 8, 9, 10, 11 */
  'WWW DD-MM-YY', 'WWW DD-MMM-YY', 'WWW DD-MM-YYYY', 'WWW DD-MMM-YYYY', /* 12, 13, 14, 15 */
  'WWW DDth MM YYYY', 'WWW DDth MMM YYYY', 'WWW DDth MMM YYYY', 'DDth MMMMMMMMM YYYY', /* 16, 17, 18, 19 */
  'WWW DD MMMMMMMMM YY', 'WWW DD MMMMMMMMM YYYY', 'WWW DD MMMMMMMMM YYYY', 'WWW DDth MMMMMMMMM YYYY', /* 20, 21, 22, 23 */
  'WWW DDth MMMMMMMMM YYYY', 'WWWWWWWWW DD MMMMMMMMM YY', 'WWWWWWWWW DD MMMMMMMMM YY', 'WWWWWWWWW DD MMMMMMMMM YYYY', /* 24, 25, 26, 27 */
  'WWWWWWWWW DD MMMMMMMMM YYYY', 'WWWWWWWWW DDth MMMMMMMMM YYYY' /* 28, 29 */
  );
  
function formatDate(date, length) {
  if (date == null)
    return "";
  var index = length - 4;
  var format = d_formats[index];
  // date
  var d = date.getDate();
  if (format.search(/DDth/) != -1) {
    if ((d == 1) || (d == 21) || (d == 31))
      d = d + 'st';
    else if ((d == 2) || (d == 22)) 
      d = d + 'nd';
    else if ((d == 3) || (d == 23)) 
      d = d + 'rd';
    else
      d = d + 'th';
    format = format.replace(/DDth/, d);
  }
  else {
    d = (d<10) ? ("0"+d) : d;
    format = format.replace(/DD/, d);
  }
  // day
  var day = l_days[date.getDay()];
  if (format.search(/WWWWWWWWW/) != -1) {
    format = format.replace(/WWWWWWWWW/, day);
  }
  else {
    day = day.substring(0, 3);
    format = format.replace(/WWW/, day);
  }
  // month
  if (format.search(/MMMMMMMMM/) != -1) {
    format = format.replace(/MMMMMMMMM/, l_months[date.getMonth()]);
  }
  else if (format.search(/MMM/) != -1) {
    format = format.replace(/MMM/, months[date.getMonth()]);
  }
  else {
    var m = date.getMonth() + 1;
    m = (m<10) ? ("0"+m) : m;
    format = format.replace(/MM/, m);
  }
  // year
  var y = date.getFullYear();
  y = (y<10) ? ("0"+y) : y;
  y = (y<100) ? ("0"+y) : y;
  y = (y<1000) ? ("0"+y) : y;
  y = y + "";
  if (format.search(/YYYY/) != -1) {
    format = format.replace(/YYYY/, y);
  }
  else {
    y = y.substring(2);
    format = format.replace(/YY/, y);
  }
  return format;
}

// ------------------------------------------------------------------------------------------------------------------//
// ------------------------------------------------- Time Validation ------------------------------------------------//
//
/* regular expression for:
hhmm
hh:mm
hh-mm
hh/mm
*/
var re_hhmm = /^(([01][0-9])|(2[0-3]))([\:\/\-]?)([0-5][0-9]?)?$/i;

/*
 *  function parseM4Time(str_time)
 *  Description:
 *    This function takes a String parameter to be validated as time. Allowed 
 *    time formats are:
 *      hhmm
 *      hh:mm
 *      hh-mm
 *      hh/mm
 *    It assumes time in twenty-four hour clock. 
 *
 *  Parameter(s):
 *    str_time: String - string to be validated as time.
 *
 *  Return value:
 *    If the string is a valid time, the function returns the time in mm:hh
 *    format e.g. 59:23, otherwise it returns an empty string.
 *
 */
function parseM4Time(str_time) {
  if (parseM4Time.arguments.length == 0) {
    return "";
  }
  // validate the pattern
  if (str_time.search(re_hhmm) == 0) {
  // comment the above line and un-comment the following line to allow hh[:/-]mm format
  //if (str_time.search(re_hhmm) == 0) {
    str_time = str_time.replace(/[\:\/\-]/g, "");
    str_time = str_time.substr(0, 2) + ":" + str_time.substr(2, 2);
    while (str_time.length < 5) {
      str_time += "0";
    }
  } else {
    str_time = "";
  }
  return str_time;
}

/*
 *  function allowTime(element)
 *  Description:
 *    This function is an event handler to validate user input as time. It sets the 
 *    'value' property of the 'element' to the return value of parseM4Time(). Example:
 *      <input type="text" id="txtTime" name="txtTime" onblur="allowTime(this)">
 *
 *  Parameter(s):
 *    element: Scriptable HTML form element that has a value property. The 'value'
 *             property will be validated as time.
 *
 *  Return value:
 *    true for a valid time, false otherwise.
 */
function allowTime(element) {
  // if no arguments return false
  if (allowTime.arguments.length == 0) {
    return false;
  }
  // does the element has a value property?
  if (typeof(element.value) == "undefined") {
    return false;
  }
  // blank accepted
  if (element.value == "") {
    return true;
  }

  //NBL 27-07-2001. Accept one digit
  if (element.value.length == 1){
    element.value = "0"+ element.value;
  }

  /*
  if (element.value > 24 && ((element.value).substr(0,1)) != "0" ){
    var tmp_time = new String(element.value);
    var t_hour = tmp_time.substr(0,1);
    var t_min = tmp_time.substr(1, tmp_time.length);
    if (t_min >60) {
      //alert("Invalid time -  minute greter than expected");
      return false;
    }
    element.value = "0" + element.value; 
    //alert(t_hour + "  "  + t_min);
  }*/

  // real work
  element.value = parseM4Time(element.value);
  if (element.value == "") {
    alert("Invalid Time");
    return false;
  }
  return true;
}
// ------------------------------------------------------------------------------------------------------------------//

/*
 *  function DateDiff(date1,date2)
 *  Description:
 *    Returns the number of days between two given dates 
 *
 *  Parameter(s):
 *    date1/date2 - two dates
 *
 *  Return value:
 *    the number of days difference between date1 and date2
 *    Or zero if either date1 or date2 is invalid
 */

function DateDiff(date1, date2)
{   
  var tdate1, tdate2, dfdate;

  // the real work
  tdate1 = parseM4Date(date1);
  tdate2 = parseM4Date(date2);
  if ( (tdate1 == null) || (tdate2 == null) ) return 0;

  dfdate = tdate2.valueOf() - tdate1.valueOf();
  dfdate = dfdate / 60000;
  dfdate = dfdate / 60;
  dfdate = dfdate / 24;
  
  return dfdate;
}

/*
 *  function calcNights(dir)
 *  Description:
 *    Calulates number of nights from arrival and departure date.
 *
 *  Parameter(s):
 *    dir - integer
 *      Direction of calculation 
 *      0 for nights from dates
 *      1 for departure date from nights and arrival dates (not implemented yet)
 *
 *  Return value:
 *    Number of nights.
 */
function calcNights(direction) {
  with (document.forms[0]) {
    if (direction == 0) {
      // control gets focus, calc diff between dates and put value in which
      nights.value = DateDiff(arrd.value, depd.value);
			if (nights.value == '0')
				nights.value = '';
    }
    else {
      // focus out, calc departure date from control's own value
			var adate = parseM4Date(arrd.value);
			if ((adate == null) || (arrd.value == '')) {
				arrd.value = '';
				nights.value = '';
				return;
			}
			var n = isNaN(parseInt(nights.value)) ? 0 : parseInt(nights.value);
			var tdate = new Date(adate.getFullYear(), adate.getMonth(), adate.getDate() + n);
			depd.value = formatDate(tdate, 11);
    }
  }
}

/*
 *  function calcPax() {
 *  Description:
 *    Calulates number of passengers from no. of audult and children
 *
 *  Parameter(s):
 *    None
 * 
 *  Return value:
 *    Total number of passengers.
 */
function calcPax() {
  with (document.forms[0]) {
    pax.value = isNaN(parseInt(adult.value)) ? 0 : parseInt(adult.value);
    pax.value = parseInt(pax.value) + (isNaN(parseInt(child.value)) ? 0 : parseInt(child.value));
		if (pax.value == '0')
				pax.value = '';
  }
}

/*
  validates form before submitting
*/
function validate() {
  var e_msg = new Array (
    "First name\n",
    "Last name\n",
    "Email address\n",
    "Country\n",
    "City/Town\n",
    "Arrival date\n",
    "Number of nights\n",
    "Total number of passengers\n"
  );

  with (document.forms[0]) {
    var ctrls = new Array(fname, lname, emad, country, town, arrd, nights, pax);
    // calculate values if focus didn't move properly
		var n = isNaN(parseInt(nights.value)) ? 0 : parseInt(nights.value);
		if (n > 0) 
			calcNights(1);
		else if (depd.value != '')
			calcNights(0);
		else {
			nights.value = '';
			depd.value = '';
		}
    calcPax();
    if (nights.value == 0) nights.value = '';
    if (pax.value == 0) pax.value = '';

    // check for empty
    var i = 0, msg = '', faulty = -1;
    for (i=0; i<ctrls.length; i++) {
      switch (ctrls[i].type) {
        case 'text':
          if (ctrls[i].value == '') {
            msg += e_msg[i];
            faulty = (faulty < 0) ? i : faulty;
          }
          break;

        case 'select-one':
          if (ctrls[i].selectedIndex == 0) {
            msg += e_msg[i];
            faulty = (faulty < 0) ? i : faulty;
          }
          break;

        default:
          break;
      }
    }
    if (msg != '') {
      alert("Please fill-up the following fields to submit your enquiry:\n" + msg);
      ctrls[faulty].focus();
      return false;
    }

    // check for valid values
    if (!isEmail(emad.value)) {
      alert("Please enter a valid email address");
      emad.focus();
      return false;
    }
    if (n <= 0) {
      alert("Number of nights must be greater than 0");
      nights.focus();
			//nights.select();
      return false;
    }
  }
}

/*
  check for valid email address pattern.
*/
function isEmail(text) {
  // FTA - the major fault in this expression is that it allows two consecutive dots.
  var re_email = /^[a-z][a-z0-9\.\_\-]*\@[a-z][a-z0-9\_\-]*\.[a-z0-9\.\_\-]*[[a-z0-9]$/i
  return re_email.test(text);
}

/* 
  allow only numaric input 
*/
function allowInteger() {
  if((event.keyCode < 48) || (event.keyCode > 57)) {
    event.keyCode=0;
  }
}

/*
  fill-up dropdowns for arrays. The arrays are defined in a separate .js 
  file, generated by a DTS from TAS database.
*/
function populateDropdowns() {
  var i, option;

  with (document.forms[0]) {
    for (i=0; i<arrAT.length; i++) {
      option = new Option(arrAT[i]);
      eval("apartment.options[i+1]=option");
    }
    for (i=0; i<arrBC.length; i++) {
      option = new Option(arrBC[i]);
      eval("budget.options[i+1]=option");
    }
    for (i=0; i<arrCO.length; i++) {
      option = new Option(arrCO[i]);
      eval("country.options[i+1]=option");
    }
  }
}
