jQuery(function($){

/*
 * Use DateSelector objects to keep track of checkin and checkout.
 *
 * Checkout should always be at least one day ahead of checkin
 */

    var day_in_ms = 86400000; 
    var max_stay = 30; /* days */

    //$.post('/log/', {stuff:[form,inDay,inYm,outDay,outYm]});
    var getFormElements = function()
    {
        var f = {};
        f.form = $('#availform');
        f.inDay = $('select[name=checkin_day]');
        f.inYm = $('select[name=checkin_ym]');
        f.outDay = $('select[name=checkout_day]');
        f.outYm = $('select[name=checkout_ym]');

        var errors = [];
        for(i in f) { if(!f[i].size()) {errors.push(i);} }
        if(errors.length) { return false; }

        return f;
    };

    /*
     * DateSelector consists of pair of selects, (day, yearMonth)
     *
     * eg. checkIn = new DateSelector('checkin',$Day, $Ym)
     *
     * @param string name of selector
     * @param jQ day select
     * @param jQ yearMonth select
     */
    var DateSelector = function(name,$day,$ym) {
        this.name = name;
        this.$day = $day;
        this.$ym = $ym;

        // today to +1 year
        this.firstDate = new Date();
        this.lastDate = new Date();
        this.lastDate.setDate(this.lastDate.getDate() + 363); // one year

        this.$origDayOptions = this.getDayOptions().clone();
    };

    /* call this on the checkout object */
    DateSelector.prototype.setCheckOut = function()
    {
        this.firstDate.setDate(this.firstDate.getDate()+1); // one day in advance
        this.lastDate.setDate(this.lastDate.getDate()+1); // one day in advance
    };

    DateSelector.prototype.repaintDays = function()
    {
        var firstDay = this.getFirstDay();
        var lastDay = this.getLastDay();
        var ymd = this.getYmd(); 
        /* var dow = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat']; */
        var dow = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
        var dateSelector = this;

        this.getDayOptions().each(function(i) {

            var $opt = $(this);
            var val = $opt.val();
           
            /* don't show older days at all */ 
            if(val > lastDay) { 
                $opt.addClass('hidden');
                $opt.attr('disabled','disabled'); 
                $opt.hide();
                $opt.html('');
                return true; /* don't break jq loop */
            } 
           
            /* rewrite with day of week */ 
            ymd.day = $opt.val();
            var opt_date = dateSelector.getMiddayDate(ymd);
            $opt.html([dow[opt_date.getDay()], opt_date.getDate()].join(', ')); 

            /* conceal days before today */
            if(val < firstDay) { 
                $opt.addClass('hidden');
                $opt.attr('disabled','disabled'); 
                $opt.hide();
            } else { 
                $opt.removeClass('hidden');
                $opt.removeAttr('disabled');
                $opt.show();
            }

        });
        
    };

    DateSelector.prototype.getDayOptions = function()
    {
        return this.$day.children('option');
    };


    DateSelector.prototype.getYmd = function()
    {
        var ym_split = this.$ym.val().split('-'); /* from '2008-2' */
        return { year:ym_split[0], month:ym_split[1], day:this.getSelectedDay()};
    };

    /* real month Jan = 1 */
    DateSelector.prototype.getMiddayDate = function(ymd)
    {
        d = new Date();
        d.setFullYear(ymd.year,ymd.month - 1,ymd.day); /* nb js months */
        d.setHours(12,0,0,0); 
        return d;
    };

    /* date object for this DateSelector */
    DateSelector.prototype.getDate  = function() {
        return this.getMiddayDate(this.getYmd());
    };


    /* real month Jan = 1 */
    DateSelector.prototype.setValue = function(year,month,day)
    {
        var ym = [year,month].join('-');
        
        var currentDay = this.getSelectedDay();
        var currentYm = this.$ym.val();

        if((ym == currentYm) && (day == currentDay)) {
            return false;
        }
        
        this.selectDay(day);
        this.$ym.val(ym); 
        return true;
    };

    DateSelector.prototype.isEarlierThan = function(dateSelector)
    {
        return this.getDate() < dateSelector.getDate();
    };

    DateSelector.prototype.isLaterThan = function(dateSelector)
    {
        return this.getDate() > dateSelector.getDate();
    };

    DateSelector.prototype.makeLaterThan = function(dateSelector)
    {
        if(this.isLaterThan(dateSelector)) { return false; }

        var ymd = dateSelector.getYmd();
        ymd.day++;
        var newDate = this.getMiddayDate(ymd);
        this.setValue(newDate.getFullYear(), newDate.getMonth()+1, newDate.getDate());
        this.repaintDays();
        return true;
    };
    
    DateSelector.prototype.makeEarlierThan = function(dateSelector)
    {
        if(this.isEarlierThan(dateSelector)) { return false; }

        var ymd = dateSelector.getYmd();
        ymd.day--; 
        var newDate = this.getMiddayDate(ymd);
        /* convert from javascript month */
        this.setValue(newDate.getFullYear(), newDate.getMonth()+1, newDate.getDate());
        this.repaintDays();
        return true;
    };

    
    /* how many days in this month
     *
     * converting from real to js month, so we are asking for the 0th day of next month 
     */
    DateSelector.prototype.daysInMonth = function()
    {
        var ymd = this.getYmd();
        return new Date(ymd.year, ymd.month, 0).getDate();
    };

    DateSelector.prototype.isFirstMonth = function()
    {
        var ymd = this.getYmd();
        return (this.firstDate.getFullYear() == ymd.year) && (this.firstDate.getMonth()+1 == ymd.month);
    };

    DateSelector.prototype.isLastMonth = function()
    {
        var ymd = this.getYmd();
        return (this.lastDate.getFullYear() == ymd.year) && (this.lastDate.getMonth()+1 == ymd.month);
    };

    /* get first valid day of month (to prevent bookings in the past) */
    DateSelector.prototype.getFirstDay = function()
    {
        if(this.isFirstMonth()) { return this.firstDate.getDate(); }
        return 1;
    };

    /* get last valid day of month (catch bookings past lastDate) */
    DateSelector.prototype.getLastDay = function()
    {
        if(this.isLastMonth()) { return this.lastDate.getDate(); }
        return this.daysInMonth();
    };

    /* return selected day as int */
    DateSelector.prototype.getSelectedDay = function()
    {
        return 1 * this.$day.val();
    };

    /* take numeric day and select the correct value */
    DateSelector.prototype.selectDay = function(day)
    {
        this.$day.val(day); 
    };

    /* set to first valid day - return true if fix took place */
    DateSelector.prototype.setToBottom = function()
    {
        if(this.getSelectedDay() < this.getFirstDay()) {
            this.selectDay(this.getFirstDay());
            return true;
        }
        return false;
    };

    /* set to last valid day - return true if fix took place */
    DateSelector.prototype.setToTop = function()
    {
        if(this.getSelectedDay() > this.getLastDay()) {
            this.selectDay(this.getLastDay());
            return true;
        }
        return false;
    };

    /* fix invalid day - return true if fix took place */
    DateSelector.prototype.fixDay = function()
    {
        return this.setToBottom() || this.setToTop();
    };
    

    var f = getFormElements();
    if(!f) { 
        $.post('log', {HotelAvailabilityMissing:errors});
        return;
    }

    
    checkIn = new DateSelector('In',f.inDay,f.inYm); 
    checkOut = new DateSelector('Out',f.outDay,f.outYm);
    checkOut.setCheckOut();

    /* initial repaint */
    checkIn.repaintDays();
    checkOut.repaintDays();

    f.inDay.change(function(){
        checkIn.fixDay();
        checkOut.makeLaterThan(checkIn);
    });

    f.inYm.change(function(){
        checkIn.fixDay();
        checkOut.makeLaterThan(checkIn);
        checkIn.repaintDays();
    });

    f.outDay.change(function(){
        checkOut.fixDay();
        checkIn.makeEarlierThan(checkOut);
    });

    f.outYm.change(function(){
        checkOut.fixDay();
        checkIn.makeEarlierThan(checkOut);
        checkOut.repaintDays();
    });

    /* validate */
    f.form.submit(function(){
        var warnings = [];
        var duration = (checkOut.getDate() - checkIn.getDate())/day_in_ms;
        if(duration > max_stay) {
            warnings.push('You can only book up to 30 days');
        }

        jQuery('.towns select').each(function(){
            if('' == $(this).val()) { warnings.push('Please select a town'); }
        }); 

        if(warnings.length > 0) {
            var warn = $('<div></div>')
                .hide()
                .html(warnings.join("<br>"))
                .attr('title', 'Please modify your request')
                .appendTo(document.body)
                .dialog({
                    buttons: { "Ok": function() { $(this).dialog("close"); }}
                });
            return false;
        }
        return true;
    });

    /* tie in with datepicker */
    function addDatepicker($trigger, dateSelector, $day, $ym) 
    {
        $trigger.datepicker({
            showOn: 'button', 
            buttonImage: '/themes/bkbluetheme/calendar.gif', 
            buttonImageOnly: true,
            buttonText:'choose date',
            duration: '',
            minDate: dateSelector.firstDate,
            maxDate: dateSelector.lastDate,
            onSelect: function(text,dp) {
                $day.val(dp.currentDay);
                $ym.val([dp.currentYear,dp.currentMonth + 1].join('-'));
                $ym.change();
            },
            beforeShow: function(input,dp) {
                $trigger.datepicker('setDate', dateSelector.getDate()); 
            }
        });
    }

    addDatepicker($('#checkin-calendar'), checkIn, f.inDay, f.inYm);
    addDatepicker($('#checkout-calendar'), checkOut, f.outDay, f.outYm);


});

