'use strict';

/*@
Ox.DateInput <f> DateInput Element
    options <o> Options object
        format <s|short> format can be short, medium, long
        value <d> date value, defaults to current date
        weekday <b|false> weekday
        width <o> width of individual input elements, in px
            day <n> width of day input element
            month <n> width of month input element
            weekday <n> width of weekday input element
            year <n> width of year input element
    self <o>    Shared private variable
    ([options[, self]]) -> <o:Ox.InputGroup> DateInput Element
        change <!> triggered on change of value
@*/
Ox.DateInput = function(options, self) {

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

    self.formats = {
        day: '%d',
        month: self.options.format == 'short' ? '%m' :
                (self.options.format == 'medium' ? '%b' : '%B'),
        weekday: self.options.format == 'long' ? '%A' : '%a',
        year: '%Y'
    };
    self.months = self.options.format == 'long' ? Ox.MONTHS : Ox.SHORT_MONTHS;
    self.weekdays = self.options.format == 'long' ? Ox.WEEKDAYS : Ox.SHORT_WEEKDAYS;

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

    that = Ox.InputGroup(Ox.extend(self.options, {
        id: self.options.id,
        inputs: [].concat(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
        ]),
        join: join,
        separators: [].concat(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}
        ]),
        split: split,
        width: 0
    }), self);

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

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

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

    function getDate(value) {
        return new Date(self.options.value.replace(/-/g, '/'));
    }

    function getDateInWeek(weekday, month, day, year) {
        //Ox.Log('Form', [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 getValues() {
        var date = getDate();
        return {
            day: Ox.formatDate(date, self.formats.day),
            month: Ox.formatDate(date, self.formats.month),
            weekday: Ox.formatDate(date, self.formats.weekday),
            year: Ox.formatDate(date, self.formats.year)
        };
    }

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

    function split() {
        var values = getValues();
        return [].concat(self.options.weekday ? [
            values.weekday
        ] : [], self.options.format == 'short' ? [
            values.year, values.month, values.day
        ] : [
            values.month, values.day, values.year
        ]);
    }

    return that;

};