(function() {

    // проверка
    if (!!myterra.Checkbox) return false;

    var states = {
        "0": 1,
        "1": 0,
        "2": 1
    };

    var current = null;
    $(document.body).mouseup(function(e) {
        if (current != null) {
            current.doMouseUp()
            current = null;
        }
    });

    myterra.Checkbox = myterra.extend(myterra.Observable, {

        state: null,
        el: null,
        disabled: false,

        constructor: function(el, opts) {

            myterra.inherited(this);

            this.opts = opts = myterra.applyIf(opts, {
                // умолчания
                state: 0,
                disabled: false,
                viewHint: false
            });

            this.el = el = $(el).addClass("checkbox");
            if (opts.cls != null) {
                el.addClass(opts.cls);
            }

            var self = this;

            this.setDisabled(this.opts.disabled);

            var h = function() {
                if (self.disabled === false) {
                    self.setState(states[self.state] || 0);
                }
                self.fireEvent("click", self);
                return false;
            };

            var button = this.button = $("<div class=\"button\"/>")
                .appendTo(el);
            button.click(h);

            var mdf = false, mof = false;

            var updateClass = function() {
                button.removeClass().addClass("button");
                if (self.disabled === true) return;
                if (mdo === true) {
                    if (mdf === true)
                        button.addClass("mousedown");
                    else
                        button.addClass("mouseover");
                }
            };

            this.doMouseUp = function() {
                mdf = false;
                updateClass();
            };

            button.mousedown(function(e) {
                current = self;
                mdf = true;
                updateClass();
                return false;
            });
            button.mouseup(function(e) {
                self.doMouseUp();
                return false;
            });
            button.mouseover(function(e) {
                mdo = true;
                updateClass();
            });
            button.mouseout(function(e) {
                mdo = false;
                updateClass();
            });

            var tick = this.tick = $("<div class=\"tick0\"/>").appendTo(button);

            if (opts.caption != null) {
                var a = $("<a href=\"#\"/>").text(opts.caption).appendTo(el)
                    .click(h).keypress(function(e) {
                        if (e.which == 32) {
                            h();
                            return false;
                        }
                    });
            }

            if (opts.hint) {
                if (a) {
                    a.attr("title", opts.hint);
                }
                if (opts.viewHint === true) {
                    $("<div class=\"hint\"/>").text("(" + opts.hint + ")")
                        .appendTo(el);
                }
            }

            this.setState(opts.state);

        },

        setDisabled: function(f) {
            var val = f === true;
            if (val != this.disabled) {
                if (this.disabled = val)
                    this.el.addClass("disabled");
                else
                    this.el.removeClass("disabled");
            }
        },

        setState: function(newstate) {
            if (newstate != this.state) {
                var state = this.state;
                if (this.fireEvent("beforechange", this, state, newstate) === false)
                    return false;
                this.tick.removeClass();
                this.tick.addClass("tick" + newstate);
                this.fireEvent("change", this, this.state = newstate);
            }
        },

        getState: function() {
            return this.state;
        },

        setChecked: function(f) {
            this.setState(f === true ? 1 : 0);
        },

        getChecked: function() {
            return this.state === 1;
        }

    });

})();
