/**
 * Our particular implementation of Control.Rating.
 */
var RatingControl = Class.create({
    /**
     * @var Object
     */
    parameters: {
        average: 0.0,
        averageCssClassName: 'rating_average',
        containerCssId: 'rating_container',
        contentId: null,
        cssClassName: 'rating',
        labelCssId: 'rating_label',
        labelWhenRated: 'You rated this',
        loggedIn: false,
        onClickWhenLoggedOut: null,
        rated: false
    },

    /**
     * @var Control.Rating
     */
    control: null,

    /**
     * Constructor.
     * 
     * @see   parameters
     * @param Object parameters Parameters
     */
    initialize: function(parameters) {
        Object.extend(this.parameters, parameters || {});
        if (this.parameters.rated) {
            this._markAsRated();
        }

        this._updateAverage(this.parameters.average);

        // Create Control.Rating instance
        this.control = new Control.Rating(this.parameters.cssClassName, {
            value: this._getRating(this.parameters.average),
            rated: this.parameters.rated
        });

        // Handle logged out users
        if (!this.parameters.loggedIn) {
            this.control.disable();
            if (Object.isFunction(this.parameters.onClickWhenLoggedOut)) {
                var eventHandler = this.parameters.onClickWhenLoggedOut;
                $$('#' + this.parameters.cssClassName + ' a').each(function(star) {
                    Event.observe(star, 'click', eventHandler);
                });
            }
        }

        // Update the current average when the control is updated
        this.control.observe('afterChange', function() {
            new Ajax.Request('/channel/addrating/' + this.parameters.contentId, {
                parameters: {rating: this.control.value},
                onSuccess: function(response) {
                    this._updateAverage(response.responseText);
                }.bind(this)
            })
            this._markAsRated();
        }.bindAsEventListener(this));
    },

    /**
     * Updates the average rating in the view.
     * 
     * @param Number rating Rating
     */
    _updateAverage: function(rating) {
        $(this.parameters.averageCssClassName).innerHTML = rating;
    },

    /**
     * Sets the label in the view to reflect rated status.
     */
    _markAsRated: function() {
        var container = $(this.parameters.containerCssId);
        var width     = (container.clientWidth + 50) + 'px';
        container.style.width = width;
        $(this.parameters.labelCssId).innerHTML = this.parameters.labelWhenRated;
    },

    /**
     * Gets a rating appropriate for use with Control.Rating.  Control.Rating 
     * doesn't seem to handle fractions correctly (3.1 == 3.5 == 3.9), so we're
     * going to be selective about what fractions we give it.
     * 
     * @param  Number rating Rating
     * @return Number 
     */
    _getRating: function(rating) {
        var fraction = rating - parseInt(rating);

        if (fraction) {
            if (fraction < 0.25) {
                rating = Math.floor(rating);
            } else if (fraction >= 0.75) {
                rating = Math.ceil(rating);
            } else {
                rating = parseInt(rating) + 0.5;
            }
        }

        return rating;
    }
});