/**
* @author Ryan Johnson <http://saucytiger.com/>
* @copyright 2008 PersonalGrid Corporation <http://personalgrid.com/>
* @package LivePipe UI
* @license MIT
* @url http://livepipe.net/control/rating
* @require prototype.js, livepipe.js
*/
 
if(typeof(Prototype) == "undefined")
  throw "Control.Rating requires Prototype to be loaded.";
if(typeof(Object.Event) == "undefined")
  throw "Control.Rating requires Object.Event to be loaded.";
 
Control.Rating = Class.create({
  initialize: function(container,options){
    Control.Rating.instances.push(this);
    this.value = false;
    this.links = [];
    this.container = $(container);
    this.container.update('');
    this.options = {
      min: 1,
      max: 5,
      rated: false,
      input: false,
      reverse: false,
      capture: true,
      multiple: false,
      classNames: {
        off: 'rating_off',
        half: 'rating_half',
        on: 'rating_on',
        selected: 'rating_selected'
      },
      updateUrl: false,
      updateParameterName: 'value',
      afterChange: Prototype.emptyFunction
    };
    Object.extend(this.options,options || {});
    if(this.options.value){
      this.value = this.options.value;
      delete this.options.value;
    }
    if(this.options.input){
      this.options.input = $(this.options.input);
      this.options.input.observe('change',function(input){
        this.setValueFromInput(input);
      }.bind(this,this.options.input));
      this.setValueFromInput(this.options.input,true);
    }
    var range = $R(this.options.min,this.options.max);
    (this.options.reverse ? $A(range).reverse() : range).each(function(i){
      var link = this.buildLink(i);
      this.container.appendChild(link);
      this.links.push(link);
    }.bind(this));
    this.setValue(this.value || this.options.min - 1,false,true);
  },
  buildLink: function(rating){
    var link = $(document.createElement('a'));
    link.value = rating;
    if(this.options.multiple || (!this.options.rated && !this.options.multiple)){
      link.href = '';
      link.onmouseover = this.mouseOver.bind(this,link);
      link.onmouseout = this.mouseOut.bind(this,link);
      link.onclick = this.click.bindAsEventListener(this,link);
    }else{
      link.style.cursor = 'default';
      link.observe('click',function(event){
        Event.stop(event);
        return false;
      }.bindAsEventListener(this));
    }
    link.addClassName(this.options.classNames.off);
    return link;
  },
  disable: function(){
    this.links.each(function(link){
      link.onmouseover = Prototype.emptyFunction;
      link.onmouseout = Prototype.emptyFunction;
      link.onclick = Prototype.emptyFunction;
      link.observe('click',function(event){
        Event.stop(event);
        return false;
      }.bindAsEventListener(this));
      link.style.cursor = 'default';
    }.bind(this));
  },
  setValueFromInput: function(input,prevent_callbacks){
    this.setValue((input.options ? input.options[input.options.selectedIndex].value : input.value),true,prevent_callbacks);
  },
  setValue: function(value,force_selected,prevent_callbacks){
    this.value = value;
    if(this.options.input){
      if(this.options.input.options){
        $A(this.options.input.options).each(function(option,i){
          if(option.value == this.value){
            this.options.input.options.selectedIndex = i;
            throw $break;
          }
        }.bind(this));
      }else
        this.options.input.value = this.value;
    }
    this.render(this.value,force_selected);
    if(!prevent_callbacks){
      if(this.options.updateUrl){
        var params = {};
        params[this.options.updateParameterName] = this.value;
        new Ajax.Request(this.options.updateUrl,{
          parameters: params
        });
      }
      this.notify('afterChange',this.value);
    }
  },
  render: function(rating,force_selected){
    (this.options.reverse ? this.links.reverse() : this.links).each(function(link,i){
      if(link.value <= Math.ceil(rating)){
        link.className = this.options.classNames[link.value <= rating ? 'on' : 'half'];
        if(this.options.rated || force_selected)
          link.addClassName(this.options.classNames.selected);
      }else
        link.className = this.options.classNames.off;
    }.bind(this));
  },
  mouseOver: function(link){
    this.render(link.value,true);
  },
  mouseOut: function(link){
    this.render(this.value);
  },
  click: function(event,link){
    this.options.rated = true;
    this.setValue((link.value ? link.value : link),true);
    if(!this.options.multiple)
      this.disable();
    if(this.options.capture){
      Event.stop(event);
      return false;
    }
  }
});
Object.extend(Control.Rating,{
  instances: [],
  findByElementId: function(id){
    return Control.Rating.instances.find(function(instance){
      return (instance.container.id && instance.container.id == id);
    });
  }
});
Object.Event.extend(Control.Rating);