/**
* @author alexander.farkas
* @version 1.4.1
*/
(function($) {
    var baseClasses = /ui-checkbox|ui-radio/;
    $.widget('ui.checkBox', {
        options: {
            hideInput: true,
            addVisualElement: true,
            addLabel: true,
            _delegated: false
        },
        _create: function() {
            var that = this,
				opts = this.options
			;

            if (!this.element.is(':radio,:checkbox')) {
                if ($.nodeName(this.element[0], 'input')) { return false; }
                this._addDelegate();
                this.updateContainer();
                return false;
            }
            this.labels = $([]);

            this.checkedStatus = false;
            this.disabledStatus = false;
            this.hoverStatus = false;

            this.radio = (this.element.is(':radio'));

            this.visualElement = $([]);
            if (opts.hideInput) {
                this.element
					.addClass('ui-helper-hidden-accessible')
				;
                if (opts.addVisualElement) {
                    this.visualElement = $('<span />')
						.addClass(this.radio ? 'ui-radio' : 'ui-checkbox')
					;
                    this.element.after(this.visualElement[0]);
                }
            }

            if (opts.addLabel) {
                this.labels = $('label[for=' + this.element.attr('id') + ']')
					.addClass(this.radio ? 'ui-radio' : 'ui-checkbox')
				;
            }
            if (!opts._delegated) {
                this._addEvents();
            }
            this.initialized = true;
            this.reflectUI({ type: 'initialReflect' });
            return undefined;
        },
        updateContainer: function() {
            if (!this.element.is(':radio,:checkbox') && !$.nodeName(this.element[0], 'input')) {
                $('input', this.element[0])
					.filter(function() {
					    return !($.data(this, 'checkBox'));
					})
					.checkBox($.extend({}, this.options, { _delegated: true }))
				;
            }
        },
        _addDelegate: function() {
            var opts = this.options,

				toggleHover = function(e, that) {
				    if (!that) { return; }
				    that.hover = !!(e.type == 'focus' || e.type == 'mouseenter' || e.type == 'focusin' || e.type == 'mouseover');
				    that._changeStateClassChain.call(that);
				    return undefined;
				}
			;


            this.element
				.bind('click', function(e) {
				    if (!$.nodeName(e.target, 'input')) { return; }
				    var inst = ($.data(e.target) || {}).checkBox;
				    if (!inst) { return; }
				    inst.reflectUI.call(inst, e.target, e);
				})
				.bind('focusin.checkBox focusout.checkBox', function(e) {
				    if (!$.nodeName(e.target, 'input')) { return; }
				    var inst = ($.data(e.target) || {}).checkBox;
				    toggleHover(e, inst);
				})
			;

            if (opts.hideInput) {
                this.element
					.bind('usermode', function(e) {
					    if (!e.enabled) { return; }
					    $('input', this).each(function() {
					        var inst = ($.data(this) || {}).checkBox;
					        (inst && inst.destroy.call(inst, true));
					    });
					})
				;
            }

            if (opts.addVisualElement) {
                this.element
					.bind('mouseover.checkBox mouseout.checkBox', function(e) {
					    if (!$.nodeName(e.target, 'span')) { return; }
					    var inst = ($.data($(e.target).prev()[0]) || {}).checkBox;
					    toggleHover(e, inst);
					})
					.bind('click.checkBox', function(e) {
					    if (!$.nodeName(e.target, 'span') || !baseClasses.test(e.target.className || '')) { return; }
					    $(e.target).prev()[0].click();
					    return false;
					})
				;
            }
            if (opts.addLabel) {
                this.element
					.delegate('label.ui-radio, label.ui-checkbox', 'mouseenter.checkBox mouseleave.checkBox', function(e) {
					    var inst = ($.data(document.getElementById($(this).attr('for'))) || {}).checkBox;
					    toggleHover(e, inst);
					});
            }

        },
        _addEvents: function() {
            var that = this,

				opts = this.options,

				toggleHover = function(e) {
				    if (that.disabledStatus) {
				        return false;
				    }
				    that.hover = (e.type == 'focus' || e.type == 'mouseenter');
				    that._changeStateClassChain();
				    return undefined;
				}
			;

            this.element
				.bind('click.checkBox', $.proxy(this, 'reflectUI'))
				.bind('focus.checkBox blur.checkBox', toggleHover)
			;
            if (opts.hideInput) {
                this.element
					.bind('usermode', function(e) {
					    (e.enabled &&
	                        that.destroy.call(that, true));
					})
				;
            }
            if (opts.addVisualElement) {
                this.visualElement
						.bind('mouseenter.checkBox mouseleave.checkBox', toggleHover)
						.bind('click.checkBox', function(e) {
						    that.element[0].click();
						    return false;
						})
					;
            }
            if (opts.addLabel) {
                this.labels.bind('mouseenter.checkBox mouseleave.checkBox', toggleHover);
            }
        },
        _changeStateClassChain: function() {
            var allElements = this.labels.add(this.visualElement),
				stateClass = '',
				baseClass = 'ui-' + ((this.radio) ? 'radio' : 'checkbox')
			;

            if (this.checkedStatus) {
                stateClass += '-checked';
                allElements.addClass(baseClass + '-checked');
            } else {
                allElements.removeClass(baseClass + '-checked');
            }

            if (this.disabledStatus) {
                stateClass += '-disabled';
                allElements.addClass(baseClass + '-disabled');
            } else {
                allElements.removeClass(baseClass + '-disabled');
            }
            if (this.hover) {
                stateClass += '-hover';
                allElements.addClass(baseClass + '-hover');
            } else {
                allElements.removeClass(baseClass + '-hover');
            }

            baseClass += '-state';
            if (stateClass) {
                stateClass = baseClass + stateClass;
            }

            function switchStateClass() {
                var classes = this.className.split(' '),
					found = false;
                $.each(classes, function(i, classN) {
                    if (classN.indexOf(baseClass) === 0) {
                        found = true;
                        classes[i] = stateClass;
                        return false;
                    }
                    return undefined;
                });
                if (!found) {
                    classes.push(stateClass);
                }
                this.className = classes.join(' ');
            }

            this.labels.each(switchStateClass);
            this.visualElement.each(switchStateClass);
        },
        destroy: function(onlyCss) {
            this.element.removeClass('ui-helper-hidden-accessible');
            this.visualElement.addClass('ui-helper-hidden');
            if (!onlyCss) {
                var o = this.options;
                this.element.unbind('.checkBox');
                this.visualElement.remove();
                this.labels
					.unbind('.checkBox')
					.removeClass('ui-state-hover ui-state-checked ui-state-disabled')
				;
            }
        },

        disable: function() {
            this.element[0].disabled = true;
            this.reflectUI({ type: 'manuallyDisabled' });
        },

        enable: function() {
            this.element[0].disabled = false;
            this.reflectUI({ type: 'manuallyenabled' });
        },

        toggle: function(e) {
            this.changeCheckStatus((this.element.is(':checked')) ? false : true, e);
        },

        changeCheckStatus: function(status, e) {
            if (e && e.type == 'click' && this.element[0].disabled) {
                return false;
            }
            this.element.attr({ 'checked': status });
            this.reflectUI(e || {
                type: 'changeCheckStatus'
            });
            return undefined;
        },

        propagate: function(n, e, _noGroupReflect) {
            if (!e || e.type != 'initialReflect') {
                if (this.radio && !_noGroupReflect) {
                    //dynamic
                    $(document.getElementsByName(this.element.attr('name')))
						.checkBox('reflectUI', e, true);
                }
                return this._trigger(n, e, {
                    options: this.options,
                    checked: this.checkedStatus,
                    labels: this.labels,
                    disabled: this.disabledStatus
                });
            }
            return undefined;
        },

        reflectUI: function(e) {

            var oldChecked = this.checkedStatus,
				oldDisabledStatus = this.disabledStatus
			;

            this.disabledStatus = this.element.is(':disabled');
            this.checkedStatus = this.element.is(':checked');

            if (this.disabledStatus != oldDisabledStatus || this.checkedStatus !== oldChecked) {
                this._changeStateClassChain();

                (this.disabledStatus != oldDisabledStatus &&
					this.propagate('disabledChange', e));

                (this.checkedStatus !== oldChecked &&
					this.propagate('change', e));
            }

        }
    });
})(jQuery);

