/* jscalendar glue
 *
 * Expects one hidden calendar field, and up to 6 extra calendar fields with
 * the same id as the hidden field, with _year, _month, _day, _hour, _minute
 * and _ampm added. These fields are expected to be single selects, although
 * _year can be a hidden field as well. The _hour and _minute fields are
 * optional, is is the _ampm field. See calendar_macros.pt for a complete
 * example
 */
if (typeof(plone)=='undefined')
    var plone = {};

(function($) { 

plone.jscalendar = {
    _calendar: null,
    _current_input: null,
    _field_names: ['year', 'month', 'day', 'hour', 'minute', 'ampm'],
    
    // All calendar fields
    _fields: function(selector) {
        if (selector === undefined) selector = plone.jscalendar._current_input;
        var fields = {field: $(selector)};
        $.each(plone.jscalendar._field_names, function() {
            fields[this] = $(selector + '_' + this);
        });
        return fields;
    },
    
    // Attach event handlers on load
    init: function() {
        $('.plone_jscalendar > input:hidden').each(function() {
            var selector = '#' + this.id;
            $.each(plone.jscalendar._fields(selector), function() {
                this.filter('select').bind(
                    'change.plone.jscalendar', {selector: selector}, 
                    plone.jscalendar.update_hidden);
            });
        });
    },
    
    // show calendar popup
    show: function(input_id, yearStart, yearEnd) {
        var cal = plone.jscalendar._cal;
        if (!cal) {
            cal = plone.jscalendar._cal = new Calendar(
                    // firstdDay, datestr, onSelect, onClose
                    1, null, plone.jscalendar.handle_select, 
                    plone.jscalendar.handle_close
            );
            cal.create();
        } else
            cal.hide();
        
        plone.jscalendar._current_input = input_id;
        var fields = plone.jscalendar._fields();
        var anchor = fields.month;
        cal.setRange(yearStart, yearEnd);
        
        // Set calendar popup date to currently selected values
        if (fields.year.val() > 0)  cal.date.setFullYear(fields.year.val());
        if (fields.month.val() > 0) cal.date.setMonth(fields.month.val() - 1);
        if (fields.day.val() > 0)   cal.date.setDate(fields.day.val());
        cal.refresh();
        cal.showAtElement(anchor.get(0), null);
        return false;
    },
    
    // handle calendar popup date select
    handle_select: function(cal, date) {
        var fields = plone.jscalendar._fields();
        var yearValue = date.substring(0,4);
        
        if ($.nodeName(fields.year.get(0), 'select') && 
            !fields.year.children('option[value=' + yearValue + ']').length) {
            // insert missing year into the options list
            var options = fields.year.get(0).options;
            for (var i=options.length; i--; i > 0) {
                if (options[i].value > yearValue)
                    options[i + 1] = new Option(options[i].value, 
                                                options[i].text);
                else {
                    options[i + 1] = new Option(yearValue, yearValue);
                    break;
                }
            }
        }
        
        fields.year.val(yearValue);
        fields.month.val(date.substring(5, 7));
        fields.day.val(date.substring(8, 10));
        plone.jscalendar.update_hidden();
    },
    
    // handle calendar popup close
    handle_close: function(cal) { cal.hide(); },
    
    // updates a hidden date field with the current values of the widgets
    update_hidden: function(e) {
        var val = '';
        var f = plone.jscalendar._fields(e && e.data.selector);
        
        if (e && e.target.selectedIndex === 0) {
            // Reset widgets; only the time widgets if this is a time select box.
            var type = e.target.id.substr(e.data.selector.length);
            var filter = $.inArray(type, ['hour', 'minute', 'ampm']) > -1 ?
                'select[id$=hour],select[id$=minute],select[id$=ampm]': 'select';
            $.each(f, function() { this.filter(filter).attr('selectedIndex', 0); });
        } else if (f.year.val() > 0 && f.month.val() > 0 && f.day.val() > 0) {
            // ISO date string
            val = [f.year.val(), f.month.val(), f.day.val()].join('-');
            
            var date = new Date(val.replace(/-/g, '/'));
            if (date.print('%Y-%m-%d') != val) {
                // Date turnes illegal dates into legal ones, update widgets
                val = date.print('%Y-%m-%d');
                f.year.val(val.substring(0, 4));
                f.month.val(val.substring(5, 7));
                f.day.val(val.substring(8, 10));
            }
            
            // optional time
            if (f.hour.length && f.minute.length) {
                val += " " + [f.hour.val(), f.minute.val()].join(':');
                if (f.ampm.length) val += " " + f.ampm.val();
            }
        }
        
        f.field.val(val);
    }
};

})(jQuery);

// initialize fields
(function($) { 
    $(plone.jscalendar.init);
})(jQuery);
