
(function() {
    Rater = Class.create({
        initialize:     function(element, options)
        {
            this.element = $(element);
            this.options = Object.extend({
                min:        1,
                max:        5,
                value:      false,
                locked:     false,
                lockOnClick: true,
                updateUrl:  false,
                classes:    {
                    container:      'rater_container',
                    off:            'rater_off',
                    on:             'rater_on',
                    selected:       'rater_selected'
                },
                onComplete: Prototype.emptyFunction,
                onSuccess:  Prototype.emptyFunction,
                onFailure:  Prototype.emptyFunction,
                onChange:   Prototype.emptyFunction
            }, options || {});
            
            if (!this.options.value) this.options.value = this.options.max;
            
            this.create();
        },
        
        create:         function()
        {
            var rater = new Element('div', {'class': this.options.classes.container});
            var rater_option;
            var className;
            for (var i = this.options.min; i <= this.options.max; i++) {
                if (i == this.options.value) {
                    className = this.options.classes.selected;
                } else if (i < this.options.value) {
                    className = this.options.classes.on;
                } else {
                    className = this.options.classes.off;
                }
                rater_option = new Element('a', {href: '#', 'class': className, value: i});
                if (!this.options.locked) {
                    rater_option.observe('click', this.clickRater.bindAsEventListener(this));
                    rater_option.observe('mouseover', this.hoverRater.bindAsEventListener(this));
                }
                rater.insert({bottom: rater_option});
            }
            rater.observe('mouseout', this.resetRater.bindAsEventListener(this));
            this.element.update(rater);
            
            this.setLocked(this.options.locked);
            
            return this;
        },
        
        clickRater:   function(event)
        {
            var element = event.element();
            event.stop();
            
            if (this.options.locked) return;
            var value = element.readAttribute('value');
            this.setValue(value);
            if (this.options.updateUrl) {
                new Ajax.Request(this.options.updateUrl, {
                    parameters:         {value: value},
                    onComplete:         this.options.onComplete,
                    onSuccess:          this.options.onSuccess,
                    onFailure:          this.options.onFailure
                });
            }
            
            // Remove mouseover observers
            if (this.options.lockOnClick) {
                this.element.select('.' + this.options.classes.container + ' a').invoke('stopObserving', 'mouseover');
                this.setLocked(true);
            }
        },
        
        hoverRater:   function(event)
        {
            var rater_option = event.findElement('a');
            if (rater_option.hasAttribute('value')) this.previewValue(rater_option.readAttribute('value'));
        },
        
        resetRater:   function()
        {
            this.previewValue(this.options.value);
        },
        
        previewValue:   function(value)
        {
            // Remove all class names
            this.element.select('a').each(function(rater_option) {
                if (!rater_option.hasAttribute('value')) return;
                var rater_option_value = parseInt(rater_option.readAttribute('value'));
                rater_option.writeAttribute('class', '');
                
                if (rater_option_value == value) {
                    rater_option.addClassName(this.options.classes.selected);
                } else if (rater_option_value < value) {
                    rater_option.addClassName(this.options.classes.on);
                } else {
                    rater_option.addClassName(this.options.classes.off);
                }
            }.bind(this));
        },
        
        setValue:       function(value)
        {
            this.options.value = value;
            
            return this;
        },
        
        getValue:       function(value)
        {
            return this.options.value;
        },
        
        setLocked:      function(value)
        {
            this.options.locked = (value);
            if (value) {
                this.element.addClassName('rater_container_locked');
            } else {
                this.element.removeClassName('rater_container_locked');
            }
            return this;
        },
        
        isLocked:       function()
        {
            return this.options.locked;
        }
    });

    if (!window.RT) window.RT = {};
    window.RT.Rater = Rater;
    
    document.fire('rt:plugin:rater:loaded');
})();