  var calHelper = function() {
    var arrive;
    var depart;
    var minStartDate;
    var maxStartDate;
    var arriveEl;
    var departEl;
    var minLengthOfStay;
    var format= "m/d/yy";
    var areEqual = function(date1, date2) {
        if (date1 === undefined || date1 === null || date2 === undefined || date2 === null) {
            return false;
        }
        return date1.valueOf() == date2.valueOf();
    };
    var setArrive = function(dateText) {
        if (dateText === "") {
            arrive = null;
        } else {
            arrive = calHelper.parse(dateText);
        }
    };
    var setDepart = function(dateText) {
        if (dateText === "") {
            depart = null;
        } else {
            depart = calHelper.parse(dateText);
        }
    };
    var update = function() {
        setArrive(arriveEl.val());
        setDepart(departEl.val());
    };
    var normalizeDate = function(date) {
        date.setMinutes(0);
        date.setSeconds(0);
        date.setHours(0);
        date.setMilliseconds(0);
        return date;
    };
    var ensureDateRange = function() {
        if(arrive !== null && arrive !== undefined && depart !== null && depart !== undefined) {
            if (arrive < depart) {
                var temp = arriveEl.val();
                arriveEl.val(departEl.val());
                departEl.val(temp);
                update();
            }
        }
    };
    var addYears = function(date, y) {
        date.setFullYear(date.getFullYear() + y);
        return date;
    };
    var addDays = function(date, d) {
        date.setDate(date.getDate() + d);
        return date;
    };
    var dateDiffInDays = function(date1, date2) {
        var millisecondsInDay = 1000 * 60 * 60 * 24;
        return Math.ceil((date2.getTime() - date1.getTime())/millisecondsInDay);
    };
    return {
    init:
        function() {
            $(document).ready(
                              function() {
                                  minStartDate = normalizeDate(new Date());
                                  maxStartDate = normalizeDate(addDays(addYears(new Date(), 1), -1));
                                  arriveEl = $(".arrive > input");
                                  arriveEl.change(update);
                                  departEl = $(".depart > input");
                                  departEl.change(update);
                                  minLengthOfStay = Number($("#minLengthOfStay > input").val()); 
                                  update();
                                  //Set common options
                                  var options = {dateFormat:format,
                                                 gotoCurrent:true,
                                                 numberOfMonths:2,
                                                 minDate:"+1D",
                                                 maxDate:"+1Y",
                                                 beforeShowDay:calHelper.beforeShowDay,
                                                 changeMonth:true};
                                  //Set options for arrive
                                   options.onSelect = calHelper.onArriveSelect;
                                  $("#" + arriveEl.attr("id")).datepicker(options);
                                  //Set options for depart
                                  options.onSelect = calHelper.onDepartSelect;
                                  options.maxDate = "+1Y +1D";
                                  $("#" + departEl.attr("id")).datepicker(options);
                              });
        },
            validate:
        function() {
            if (arriveEl.val() == "" && departEl.val() == "" ) {
                return true;
            }
            if (arrive === null || arrive === undefined || depart === null || depart === undefined) {
                //Invalid date
                if ((arrive === null || arrive === undefined) && (depart === null || depart === undefined)) {
                    alert("Please enter valid arrival and departure dates.");
                    return false;
                }
                if (arrive === null || arrive === undefined) {
                    alert("Please enter a valid arrival date.");
                    return false;
                }
                if (depart === null || depart === undefined) {
                    alert("Please enter a valid departure date.");
                    return false;
                }
            }
            if (depart <= arrive) {
                alert("Arrival must precede departure.");
                return false;
            } 
            if (arrive < minStartDate || arrive > maxStartDate) {
                alert("Travel must take place within one year from today.");
                return false;
            }
            if (dateDiffInDays(arrive, depart) < minLengthOfStay) {
                alert("Minimum length of stay is " + minLengthOfStay + (minLengthOfStay == 1 ? " night." : " nights."));
                return false;
            }
            return true;
        },
            onArriveSelect:
        function(dateText, dp) {
            arrive = calHelper.parse(dateText);
            //Synchronize the default date on departure calendar
            $("#" + departEl.attr("id")).datepicker("option", "defaultDate", arrive);
            if (depart !== null && depart !== undefined && depart <= arrive) {
                $("#" + departEl.attr("id")).datepicker("setDate", null);
                depart = null;
            }
        },
            onDepartSelect:
        function(dateText, dp) {
            depart = calHelper.parse(dateText);
            //Synchronize the default date on arrival calendar
            $("#" + arriveEl.attr("id")).datepicker("option", "defaultDate", depart);
            if (arrive !== null && arrive !== undefined && arrive >= depart) {
                $("#" + arriveEl.attr("id")).datepicker("setDate", null);
                arrive = null;
            }
        },
            beforeShowDay:
        function(date) {
            if (areEqual(arrive, date)) {
                return [true, "arrive-day"];
            }
            if (areEqual(depart, date)) {
                return [true, "depart-day"];
            }
            if (arrive !== null && depart !== null && date > arrive && date < depart) {
                return [true, "stay"];
            }
            return [ true, "" ];
        },
            parse:
        function(dateText) {
            try {
                return $.datepicker.parseDate(format, dateText);
            } catch (e) {
                alert("Sorry, we don't recognize the date you typed in. Please use the following format: m/d/yyyy");
            }
        }
            };
}();
calHelper.init();
