/**
 * Simple rating script
 * 
 * Visit http://rightjs.org/ui/rater for details
 *
 * Copyright (C) 2009-2010 Nikolay V. Nemshilov
 */
if (!self.RightJS) throw "Gimme RightJS";
/**
 * The Rating widget
 *
 * Copyright (C) 2009-2010 Nikolay V. Nemshilov
 */
var Rater = new Class(Observer, {
  extend: {
    EVENTS: $w('change hover send'),
    
    Options: {
      size:          5,      // number of stars in the line
      value:         null,   // default value
      update:        null,   // an element to update
      
      disabled:      false,  // if it should be disabled
      disableOnVote: false,  // if it should be disabled when user clicks a value
      
      url:           null,   // an url to send results with AJAX
      param:         'rate', // the value param name 
      Xhr:           null    // additional Xhr options
    },
        
    // DEPRECATED: searches and initializes rating units
    rescan: function(scope) {}
  },
  
  /**
   * basic constructor
   *
   * @param mixed element reference or an options hash
   * @param Object options hash
   */
  initialize: function() {
    var args = $A(arguments);
    
    this.element = (args[0] && !isHash(args[0])) ? $(args[0]) : null;
    this.$super(isHash(args.last()) ? args.last() : this.element ? eval('('+this.element.get('data-rater-options')+')') : null);
    
    if (!this.element) this.element = this.build();
    
    if (!this.options.value)
      this.options.value = this.element.select('.right-rater-glow').length;
    
    this.element._rater = this.init();
  },
  
  /**
   * Sets the element value
   *
   * @param Number or String value
   * @return Rater this
   */
  setValue: function(value) {
    if (!this.disabled()) {
      // converting the type and rounding the value
      value = isString(value) ? value.toInt() : value;
      value = isNumber(value) ? value.round() : 0;
      
      // checking constraints
      if (value > this.options.size) value = this.options.size;
      else if (value < 0) value = 0;
      
      this.highlight(value);
      
      if (this.value != value) {
        this.fire('change', this.value = value, this);
      }
    }
    
    return this;
  },
  
  /**
   * Returns the current value of the rater
   *
   * @return Number value
   */
  getValue: function() {
    return this.value;
  },
  
  /**
   * Inserts the rater into the given element
   *
   * @param mixed element reference
   * @param String optional position
   * @return Rater this
   */
  insertTo: function(element, position) {
    this.element.insertTo(element, position);
    return this;
  },
  
  /**
   * Assigns the unit to work with an input element
   *
   * @param mixed element reference
   * @return Rater this
   */
  assignTo: function(element) {
    var assign  = function(element, value) {
      if (element = $(element)) {
        if (value === undefined || value === null) value = '';
        element[element.setValue ? 'setValue' : 'update'](''+value);
      }
    }.curry(element);
    
    var connect = function(element, object) {
      var element = $(element);
      if (element && element.onChange) {
        element.onChange(function() {
          this.setValue(element.value);
        }.bind(object));
      }
    }.curry(element);
    
    if ($(element)) {
      assign(this.value);
      connect(this);
    } else {
      document.onReady(function() {
        assign(this.value);
        connect(this);
      }.bind(this));
    }
    
    return this.onChange(assign);
  },
  
  /**
   * Sends an Xhr request with the current value to the options.url address
   *
   * @return Rater this
   */
  send: function() {
    if (this.options.url) {
      new Xhr(this.options.url, this.options.Xhr).send(this.options.param+"="+this.value);
      this.fire('send', this.value, this);
    }
    return this;
  },
  
  /**
   * Disables the instance
   *
   * @return Rater this
   */
  disable: function() {
    this.element.addClass('right-rater-disabled');
    return this;
  },
  
  /**
   * Enables this instance
   *
   * @return Rater this
   */
  enable: function() {
    this.element.removeClass('right-rater-disabled');
    return this;
  },
  
  /**
   * Checks if the instance is disabled
   *
   * @return boolean
   */
  disabled: function() {
    return this.element.hasClass('right-rater-disabled');
  },
  
// protected

  // callback for 'hover' event
  hovered: function(index) {
    if (!this.disabled()) {
      this.highlight(index + 1);
      this.fire('hover', index + 1, this);
    }
  },
  
  // callback for user-click
  clicked: function(index) {
    this.setValue(index + 1);
    if (this.options.disableOnVote) this.disable();
    this.send();
  },
  
  // callback when user moves the mouse out
  leaved: function() {
    this.setValue(this.value);
  },
  
  // highlights the stars
  highlight: function(number) {
    this.stars.each(function(element, i) {
      element[number - 1 < i ? 'removeClass' : 'addClass']('right-rater-glow');
    });
  },

  // initializes the script
  init: function() {
    this.stars = this.element.subNodes();
    
    this.stars.each(function(element, index) {
      element.onMouseover(this.hovered.bind(this, index))
        .onClick(this.clicked.bind(this, index));
    }, this);
    
    this.element.onMouseout(this.leaved.bind(this));
    this.setValue(this.options.value);
    
    if (this.options.disabled) this.disable();
    if (this.options.update)   this.assignTo(this.options.update);
    
    return this;
  },
  
  // builds the elements structure
  build: function() {
    var element = $E('div', {'class': 'right-rater'});
    
    this.options.size.times(function() {
      element.insert($E('div', {html: '&#9733;'}));
    });
    
    return element;
  }
});

/**
 * Document on-load trigger for units auto-discovery
 *
 * Copyright (C) 2009-2010 Nikolay V. Nemshilov
 */
document.onMouseover(function(event) {
  var target = event.target, element = [target].concat(target.parents()).first('hasClass', 'right-rater');
  
  if (element) {
    var rater = element._rater || new Rater(element);
    if (target.parentNode === element)
      target.fire('mouseover');
  }
  
});document.write("<style type=\"text/css\">div.right-rater,div.right-rater div{margin:0;padding:0;background:none;border:none;display:inline-block;*display:inline;*zoom:1;font-family:Arial;font-size:110%}div.right-rater{width:6em;height:1em;vertical-align:middle}div.right-rater div{float:left;width:1em;height:1em;line-height:1em;text-align:center;cursor:pointer;color:#888}div.right-rater div.right-rater-glow{color:brown;text-shadow:#666 .05em .05em .15em}div.right-rater-disabled div{cursor:default}</style>");