// vim: et:ts=4:sw=4:sts=4:ft=js

/*@
Ox.DateInput <f:Ox.Element> DateInput Element
    () ->              <f> DateInput Element
    (options) ->       <f> DateInput Element
    (options, self) -> <f> DateInput Element
    options <o> Options object
        format <s|short> format can be short, medium, long
        value <d> date value, defaults to now
        weekday <b|false> weekday
        width: <o> width object with day, month, weekday, year width
    self <o>    Shared private variable
    change <!> triggered on change of value   
@*/
Ox.DateInput = function(options, self) {

    var self = $.extend(self || {}, {
            options: $.extend({
                format: 'short',
                value: Ox.formatDate(new Date(), '%F'),
                weekday: false,
                width: {
                    day: 32,
                    month: options.format == 'long' ? 80 : (options.format == 'medium' ? 40 : 32),
                    weekday: options.format == 'long' ? 80 : 40,
                    year: 48
                }
            }, options)
        }),
        that;

    $.extend(self, {
        date: new Date(self.options.value.replace(/-/g, '/')),
        formats: {
            day: '%d',
            month: self.options.format == 'short' ? '%m' :
                    (self.options.format == 'medium' ? '%b' : '%B'),
            weekday: self.options.format == 'long' ? '%A' : '%a',
            year: '%Y'
        },
        months: self.options.format == 'long' ? Ox.MONTHS : $.map(Ox.MONTHS, function(v, i) {
            return v.substr(0, 3);
        }),
        weekdays: self.options.format == 'long' ? Ox.WEEKDAYS : $.map(Ox.WEEKDAYS, function(v, i) {
            return v.substr(0, 3);
        })
    });

    self.$input = $.extend(self.options.weekday ? {
        weekday: new Ox.Input({
                autocomplete: self.weekdays,
                autocompleteReplace: true,
                autocompleteReplaceCorrect: true,
                id: 'weekday',
                value: Ox.formatDate(self.date, self.formats.weekday),
                width: self.options.width.weekday
            })
            .bindEvent('autocomplete', changeWeekday),
    } : {}, {
        day: new Ox.Input({
                autocomplete: $.map(Ox.range(1, Ox.getDaysInMonth(
                    parseInt(Ox.formatDate(self.date, '%Y'), 10),
                    parseInt(Ox.formatDate(self.date, '%m'), 10)
                ) + 1), function(v, i) {
                    return self.options.format == 'short' ? Ox.pad(v, 2) : v.toString();
                }),
                autocompleteReplace: true,
                autocompleteReplaceCorrect: true,
                id: 'day',
                value: Ox.formatDate(self.date, self.formats.day),
                textAlign: 'right',
                width: self.options.width.day
            })
            .bindEvent('autocomplete', changeDay),
        month: new Ox.Input({
                autocomplete: self.options.format == 'short' ? $.map(Ox.range(1, 13), function(v, i) {
                    return Ox.pad(v, 2);
                }) : self.months,
                autocompleteReplace: true,
                autocompleteReplaceCorrect: true,
                id: 'month',
                value: Ox.formatDate(self.date, self.formats.month),
                textAlign: self.options.format == 'short' ? 'right' : 'left',
                width: self.options.width.month
            })
            .bindEvent('autocomplete', changeMonthOrYear),
        year: new Ox.Input({
                autocomplete: $.map($.merge(Ox.range(1900, 3000), Ox.range(1000, 1900)), function(v, i) {
                    return v.toString();
                }),
                autocompleteReplace: true,
                autocompleteReplaceCorrect: true,
                id: 'year',
                value: Ox.formatDate(self.date, self.formats.year),
                textAlign: 'right',
                width: self.options.width.year
            })
            .bindEvent('autocomplete', changeMonthOrYear)
    });

    that = new Ox.InputGroup($.extend(self.options, {
        id: self.options.id,
        inputs: $.merge(self.options.weekday ? [
            self.$input.weekday
        ] : [], self.options.format == 'short' ? [
            self.$input.year, self.$input.month, self.$input.day
        ] : [
            self.$input.month, self.$input.day, self.$input.year
        ]),
        separators: $.merge(self.options.weekday ? [
            {title: self.options.format == 'short' ? '' : ',', width: 8},
        ] : [], self.options.format == 'short' ? [
            {title: '-', width: 8}, {title: '-', width: 8}
        ] : [
            {title: '', width: 8}, {title: ',', width: 8}
        ]),
        width: 0
    }), self);

    //Ox.print('SELF', self)

    function changeDay() {
        self.options.weekday && self.$input.weekday.options({
            value: Ox.formatDate(new Date([
                self.$input.month.options('value'),
                self.$input.day.options('value'),
                self.$input.year.options('value')
            ].join(' ')), self.formats.weekday)
        });
        setValue();
    }

    function changeMonthOrYear() {
        var day = self.$input.day.options('value'),
            month = self.$input.month.options('value'),
            year = self.$input.year.options('value'),
            days = Ox.getDaysInMonth(year, self.options.format == 'short' ? parseInt(month, 10) : month);
        day = day <= days ? day : days;
        //Ox.print(year, month, 'day days', day, days)
        self.options.weekday && self.$input.weekday.options({
            value: Ox.formatDate(new Date([month, day, year].join(' ')), self.formats.weekday)
        });
        self.$input.day.options({
            autocomplete: $.map(Ox.range(1, days + 1), function(v, i) {
                return self.options.format == 'short' ? Ox.pad(v, 2) : v.toString();
            }),
            value: self.options.format == 'short' ? Ox.pad(day, 2) : day.toString()
        });
        setValue();
    }

    function changeWeekday() {
        var date = getDateInWeek(
                self.$input.weekday.options('value'),
                self.$input.month.options('value'),
                self.$input.day.options('value'),
                self.$input.year.options('value')
            );
        self.$input.month.options({value: date.month});
        self.$input.day.options({
            autocomplete: $.map(Ox.range(1, Ox.getDaysInMonth(date.year, date.month) + 1), function(v, i) {
                    return self.options.format == 'short' ? Ox.pad(v, 2) : v.toString();
                }),
            value: date.day
        });
        self.$input.year.options({value: date.year});
        setValue();
    }

    function getDateInWeek(weekday, month, day, year) {
        //Ox.print([month, day, year].join(' '))
        var date = new Date([month, day, year].join(' '));
        date = Ox.getDateInWeek(date, weekday);
        return {
            day: Ox.formatDate(date, self.formats.day),
            month: Ox.formatDate(date, self.formats.month),
            year: Ox.formatDate(date, self.formats.year)
        };
    }

    function setValue() {
        self.options.value = Ox.formatDate(new Date(self.options.format == 'short' ? [
            self.$input.year.options('value'),
            self.$input.month.options('value'),
            self.$input.day.options('value')
        ].join('/') : [
            self.$input.month.options('value'),
            self.$input.day.options('value'),
            self.$input.year.options('value')
        ].join(' ')), '%F');
    }

    /*
    function normalize() {
        var year = that.getInputById('year').options('value'),
            month = that.getInputById('month').options('value'),
            day = that.getInputById('day').options('value')
        return {
            year: year,
            month: self.options.format == 'short' ? month :
                    Ox.pad((format == 'medium' ? Ox.WEEKDAYS.map(function(v, i) {
                        return v.substr(0, 3);
                    }) : Ox.WEEKDAYS).indexOf(month), 2),
            day: Ox.pad(day, 2)
        }
    }
    */

    /*
    that.serialize = function() {
        var normal = normalize();
        return [normal.year, normal.month, normal.day].join('-');
    }
    */

    return that;

};
