/*
jQuery Ui timepickr
(c) Maxime Haineault <haineault@gmail.com> 
http://haineault.com

MIT License (http://www.opensource.org/licenses/mit-license.php
Modified under license by Daniel Wachsstock
  
*/

(function($) {
    $('<style>' +
		'.ui-timepickr {position:absolute; text-align: left; } ' +
		'.ui-timepickr ol { margin-top:2px; } ' +
		'.ui-timepickr li {float: left; font-size:.7em; padding:4px 6px 4px 6px; margin-left:2px; cursor: pointer;} ' +
		'</style>').appendTo('head');

    var menuTemplate = '<div class="ui-helper-reset ui-timepickr ui-widget" />';
    var rowTemplate = '<ol />';
    var buttonTemplate = '<li class="{className}">{label}</li>';
    function format(s, o) { // simple parameterizing strings
        for (key in o) s = s.replace('{' + key + '}', o[key]);
        return s;
    }

    $.widget('ui.timepickr', {
        _init: function() {
            var ui = this, element = this.element;
            element.data('timepickr.initialValue', element.val());
            var menu = this.menu = ui._buildMenu().insertAfter(element);
            menu.children().hide();

            element.bind(this.options.trigger + '.timepickr', function() {
                ui.show();
            });

            var hover = this.options.hoverIntent && $.fn.hoverIntent ? 'hoverIntent' : 'hover';
            menu
			.data('timepickr', this)
			.css({ width: this.options.width })
			.find('li')
				.addClass('ui-state-default ui-corner-all')
				[hover](function() {
				    ui.inside = true;
				    $(this).siblings().removeClass('ui-state-hover');
				    $(this).addClass('ui-state-hover');
				    ui._redraw();
				    ui.showNextLevel(this);
				    ui.update();
				}, function() {
				    ui.inside = false;
				}).end()
			.find('ol')
				.addClass('ui-widget ui-helper-clearfix ui-helper-reset')
				.hide();

            this._redraw();

            element.blur(function(e) {
                ui.hide();
                if (ui.inside) {
                    // clicking outside the element blurs it before the click on the new element in called
                    ui._trigger('select', [e, ui]);
                }else if (ui.options.resetOnBlur) {
                    element.val(element.data('timepickr.initialValue')).change();
                }
            });

            if (this.options.val) {
                element.val(this.options.val);
            }

            if (this.options.handle) {
                $(this.options.handle).click(function() {
                    ui.show();
                    ui.element.focus();
                });
            }

            this._redraw();
        },

        update: function() {
            var val = {
                h: this.getValue('hour'),
                m: this.getValue('minute'),
                prefix: this.getValue('prefix'),
                suffix: this.getValue('suffix')
            };
            $(this.element).val(format(this.options.format, val)).change();
        },

        getValue: function(type) {
            return $('.' + type + '.ui-state-hover', this.menu).add($('.' + type + ':first', this.menu)).eq(0).text();
        },

        destroy: function() {
            this.menu.remove();
        },

        show: function() {
            this.element.data('timepickr.initialValue', this.element.val());
            this.menu.css({
                top: this.element.position().top + this.element.height() + this.options.top,
                zIndex: 1000
            });
            this.menu.find('ol:eq(0)').css('left', this.element.position().left).show();
        },

        showNextLevel: function(el) {
            $(el).closest('ol').next().show(this.options.animSpeed);
        },

        // essentially reposition each ol
        _redraw: function() {
            this.menu.css({
                top: this.element.position().top + this.element.height() + this.options.top,
                left: this.element.position().left + this.options.left
            });

            if (this.options.convention === 24) {
                var hrs = this.menu.find('ol:eq(1)');
                var dayHours = hrs.find('li').slice(0, 12);
                var nightHours = hrs.find('li').slice(12, 24);
                if (this.menu.find('ol:eq(0) li:eq(0)').hasClass('ui-state-hover')) {
                    // daytime
                    nightHours.hide();
                    dayHours.show();
                } else {
                    //nighttime
                    dayHours.hide();
                    nightHours.show();
                }
            }

            // reposition each ol
            var ols = this.menu.find('ol');
            ols.each(function(i) {
                var prevOL = $(this).prev('ol');
                // find the span that's being hovered; if nothing, use the first one (position returns the position of the first item)
                var pos = prevOL.find('.ui-state-hover:visible').add(prevOL.find('li:visible:first')).position();
                if (pos) $(this).css('margin-left', pos.left);
            });
        },

        // hide all levels
        hide: function() {
            this.menu.find('ol').hide();
        },

        activate: function(e) {
            this.element.focus();
            this.show(this.options.animSpeed);
        },

        destroy: function(e) {
            this.menu.remove();
        },

        _createRow: function(range, className) {
            var row = $(rowTemplate);
            $.each(range, function() {
                row.append($(format(buttonTemplate, { className: className, label: this.toString() })));
            });
            return row;
        },

        _getRanges12: function() {
            var o = [];
            o.push(this._createRow(['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'], 'hour'));
            o.push(this._createRow(this.options.rangeMin, 'minute'));
            o.push(this._createRow(this.options.suffix, 'suffix'));
            return o;
        },

        _getRanges24: function() {
            var o = [], opt = this.options;
            o.push(this._createRow(this.options.prefix, false, 'prefix')); // prefix is required in 24h mode
            o.push(this._createRow(
			['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23'],
			'hour'
		));
            o.push(this._createRow(this.options.rangeMin, 'minute'));
            return o;
        },

        _buildMenu: function() {
            var menu = $(menuTemplate);
            var ranges = this.options.convention === 24
								 && this._getRanges24() || this._getRanges12();
            $.each(ranges, function(i, val) {
                menu.append(val);
            });
            return menu;
        }
    });

    $.ui.timepickr.defaults = {
        top: 6,
        left: 0,
        animSpeed: 0,
        trigger: 'click',
        convention: 12, // 24, 12
        format: '{h}:{m} {suffix}',
        handle: false,
        prefix: ['00-11', '12-23'],
        suffix: ['am', 'pm'],
        rangeMin: ['00', '15', '30', '45'],
        resetOnBlur: true,
        val: false,
        hoverIntent: false
    };

})(jQuery);

