/*!
 * Denbel.ui.StarBox
 * author M.F. Endenburg
 * version 2.0
 * copyright (c) 2008, Denbel
 */

// load namespaces
Denbel.load( 'ui.StarBoxCollection' );
Denbel.load( 'ui.StarBox' );

/**
 * The star box collection
 * @var Denbel.ui.StarBoxCollection
 */
Denbel.ui.StarBoxCollection =
{
  /**
   * Array to hold all starbox objects
   * @var Array
   */
  objects: [],
  
  /**
   * Adds an object
   * @param Denbel.ui.StarBox object
   * @return int
   */
  add: function( object )
  {
    var self = Denbel.ui.StarBoxCollection;
    
    if( !self.objects )
    {
      self.objects = [];
    }
    
    self.objects.push( object );
    return ( self.objects.length - 1 );
  },
  
  /**
   * Gets an object at a given index
   * @param int index
   * @return Denbel.ui.StarBox
   */
  get: function( index )
  {
    if( !YAHOO.lang.isNumber( index ) )
    {
      return null;
    }
    
    var self = Denbel.ui.StarBoxCollection;
    
    if( self.objects.length <= index )
    {
      return null;
    }
    
    return self.objects[index];
  },
  
  /**
   * Inserts an object at a given index
   * @param Denbel.ui.StarBox object
   * @param int index
   * @return bool
   */
  insert: function( object, index )
  {
    if( !YAHOO.lang.isNumber( index ) )
    {
      return false;
    }
  
    var self = Denbel.ui.StarBoxCollection;
    
    if( !self.objects )
    {
      self.objects = [];
    }
    
    self.objects[index] = object;
    return ( self.objects[index] == object );
  },
  
  /**
   * Removes an object at a given index
   * @param int index
   * @return void
   */
  remove: function( index )
  {
    var self = Denbel.ui.StarBoxCollection;
    
    if( !self.objects )
    {
      self.objects = [];
      return;
    }
    
    if( self.objects.length <= index )
    {
      return;
    }
    
    self.objects[index] = null;
  }
};

/*******************************************************************************/

/**
 * Creates an instance of a RatingDevice
 * @param variant container
 * @param object config
 * @return RatingDevice
 */
Denbel.ui.StarBox = function( container, config )
{
	this.config = config;
  this.config.container = container;
  
  if( !this.init() )
  {
    YAHOO.log( 'Initialization failed. Are you missing any required configuration attributes?', 'error', 'Denbel.ui.StarBox' );
  }
};

/**
 * Global mouseover
 * @param HTMLElement sender
 * @param int index
 * @return void
 */
Denbel.ui.StarBox.onMouseOver = function( sender, index )
{
  var o = Denbel.ui.StarBoxCollection.get( index );
  
  if( !o.getLocked() )
  {
    o.fill( parseInt( sender.getAttribute( 'value' ) ) );
  }
};

/**
 * Global mouseout
 * @param HTMLElement sender
 * @param int index
 * @return void
 */
Denbel.ui.StarBox.onMouseOut = function( sender, index )
{
  var o = Denbel.ui.StarBoxCollection.get( index );

  if( !o.getLocked() )
  {
    o.reset();
  }
};

/**
 * Global click
 * @param HTMLElement sender
 * @param int index
 * @return void
 */
Denbel.ui.StarBox.onClick = function( sender, index )
{
  var o = Denbel.ui.StarBoxCollection.get( index );
  
  if( !o.getLocked() )
  {
    o.setValue( parseInt( sender.getAttribute( 'value' ) ) );
    o.submit( parseInt( sender.getAttribute( 'value' ) ) );
  }
};

// prototype
Denbel.ui.StarBox.prototype =
{
  /**
   * configuration attributes
   * @var object
   */
  config: null,

  /**
   * Internal array of image elements
   * @var Array
   */
  objects: [],
  
  /**
   * index of this object in collection
   * @var int
   */
  index: null,
  
  /**
   * Actual value of the starbox
   * @var int
   */
  value: null,
  
  /**
   * ID of this object
   * @var string
   */
  id: null,
  
  /**
   * Initializer
   * @return bool
   */
  init: function()
  {
    if( !this.config )
    {
      YAHOO.log( 'No configuration attributes set', 'error', 'Denbel.ui.StarBox' );
      return false;
    }
    
    /*
    initialize configuration attributes in this structure:
    config
    {
      container: <Variant>      // the string ID or HTMLElement where to put the object in to
      size: <Number>            // the number of items the element should contain
      texts: <Array>            // an array with strings containing the texts to show over each image element
      allowHalf: <Boolean>      // defines if half images are allowed
      locked: <Boolean>         // defines if the element is locked or not
      initialValue: <Number>    // the initial value of the element (defaults to zero)
      postMessage: <String>     // remote method name to post to
      postUrl: <String>         // url to post to (defaults to "/proxy.php")
      postParameters: <Array>   // array of parameters that will be posted on submit
    }
    */
    
    if( !this.config.container || !this.config.size || !this.config.postMessage )
    {
      return false;
    }
    
    this.config.container = YAHOO.util.Dom.get( this.config.container );
    
    if( !this.config.container )
    {
      return false;
    }
    
    if( !this.config.postUrl )
    {
      this.config.postUrl = '/proxy.php';
    }
    
    if( !this.config.postParameters )
    {
      this.config.postParameters = [];
    }
    
    if( !this.config.allowHalf )
    {
      this.config.allowHalf = false;
    }
    
    if( !this.config.initialValue )
    {
      this.config.initialValue = 0;
    }
    
    if( !this.config.locked )
    {
      this.config.locked = false;
    }
    
    if( !this.config.texts )
    {
      this.config.texts = [];
    }
    
    this.objects = [];
    this.value = null;
    
    this.index = Denbel.ui.StarBoxCollection.add( this );
    
    this.config.initialized = true;
    
    return true;
  },
  
  /**
   * Sets a new value for the starbox
   * @param int value
   * @return void
   */
  setValue: function( value )
  {
    if( !YAHOO.lang.isNumber( value ) )
    {
      return;
    }
    
    this.value = value;
    this.render();
  },
  
  /**
   * Gets the current value of the starbox
   * @return int
   */
  getValue: function()
  {
    return this.value;
  },
  
  /**
   * Gets the configuration object
   * @return object
   */
  getConfig: function()
  {
  	return this.config;
  },
  
  /**
   * Locks or unlocks the rating
   * @param bool value
   * @return void
   */
  setLocked: function( value )
  {
    if( !YAHOO.lang.isBoolean( value ) )
    {
      return;
    }
    
  	this.config.locked = value;
    
    if( !this.config.locked )
    {    
      YAHOO.util.Dom.removeClass( innerContainer, 'dbl-starbox-locked' );
      YAHOO.util.Dom.addClass( innerContainer, 'dbl-starbox' );
    }
    else
    {
      YAHOO.util.Dom.removeClass( innerContainer, 'dbl-starbox' );
      YAHOO.util.Dom.addClass( innerContainer, 'dbl-starbox-locked' );
    }
  	
  	Denbel.ui.StarBoxCollection.insert( this, this.index );
  },
  
  /**
   * Gets the locked status
   * @return bool
   */
  getLocked: function()
  {
  	return this.locked;
  },
  
  /**
   * Renders the device
   * @return bool
   */
  render: function()
  {
    if( !this.config.initialized )
    {
      YAHOO.log( 'StarBox not initialized', 'error', 'Denbel.ui.StarBox' );
      return false;
    }
  
  	this.objects = []; // reset objects array
    
    // temp vars
    var innerContainer = null;
    var imageElement = null;
    var imageText = null;
    
    var html = '';
    
    // create inner container
    var innerContainer = document.createElement( 'div' );
    //innerContainer.setAttribute( 'class', 'dbl-starbox' );
    innerContainer.setAttribute( 'id', 'dbl-starbox-' + this.index );
    
    html += '<div id="dbl-starbox-' + this.index + '"';
    
    if( !this.config.locked )
    {
      YAHOO.util.Dom.removeClass( innerContainer, 'dbl-starbox-locked' );
      YAHOO.util.Dom.addClass( innerContainer, 'dbl-starbox' );
      
      html += ' class="dbl-starbox"';
    }
    else
    {
      YAHOO.util.Dom.removeClass( innerContainer, 'dbl-starbox' );
      YAHOO.util.Dom.addClass( innerContainer, 'dbl-starbox-locked' );
      
      html += ' class="dbl-starbox-locked"';
    }
    
    html += '>' + "\r\n";
    
    var setToValue = this.config.initialValue;
    
    if( this.value != null )
    {
      setToValue = this.value;
    }
    
  	for( var i = 0; i < this.config.size; i++ )
  	{
      if( this.config.texts[i] )
      {
        imageText = this.config.texts[i];
      }
      else
      {
        imageText = ( i + 1 );
      }
      
      imageElement = document.createElement( 'span', "\r\n" );
      //imageElement.setAttribute( 'class', 'dbl-starbox-image' );
      imageElement.setAttribute( 'id', 'dbl-starbox-' + this.index + '-image-' + i );
      imageElement.setAttribute( 'value', ( i + 1 ) );
      
      html += '<span id="dbl-starbox-' + this.index + '-image-' + i + '" value="' + ( i + 1 ) + '"';
      
      if( i < setToValue )
      {
        if( setToValue < parseFloat( i + 0.6 ) )
        {
          YAHOO.util.Dom.removeClass( imageElement, 'dbl-starbox-image' );
          YAHOO.util.Dom.removeClass( imageElement, 'dbl-starbox-image-fill' );
          YAHOO.util.Dom.addClass( imageElement, 'dbl-starbox-image-half' );
          
          html += ' class="dbl-starbox-image-half"';
        }
        else
        {
          YAHOO.util.Dom.removeClass( imageElement, 'dbl-starbox-image' );
          YAHOO.util.Dom.removeClass( imageElement, 'dbl-starbox-image-half' );
          YAHOO.util.Dom.addClass( imageElement, 'dbl-starbox-image-fill' );
          
          html += ' class="dbl-starbox-image-fill"';
        }
      }
      else
      {
        YAHOO.util.Dom.removeClass( imageElement, 'dbl-starbox-image-fill' );
        YAHOO.util.Dom.removeClass( imageElement, 'dbl-starbox-image-half' );
        YAHOO.util.Dom.addClass( imageElement, 'dbl-starbox-image' );
        
        html += ' class="dbl-starbox-image"';
      }
      
      imageElement.setAttribute( 'title', imageText );
      html += ' title="' + imageText + '"';
      
      html += this.attachEvents( imageElement );
      html += ">\r\n</span>";
      
      innerContainer.appendChild( imageElement );
  		this.objects.push( imageElement );
  	}
    
    html += '</div>';
    this.config.container.innerHTML = '';
    
    if( YAHOO.env.ua.ie > 0 && YAHOO.env.ua.ie < 8 )
    {
      this.config.container.innerHTML = html; //Denbel.util.XmlHelper.elementToString( innerContainer );
    }
    else
    {
      this.config.container.appendChild( innerContainer );
    }
    
  	return true;
  },
  
  /**
   * Attaches events to the given image element
   * @param HTMLElement imageElement
   * @return string
   */
  attachEvents: function( imageElement )
  {
    var html = '';
    
    if( !this.config.locked )
    {
      YAHOO.util.Event.addListener( imageElement, 'mouseover', function( e, o )
      {
        YAHOO.util.Event.stopEvent( e );
      
        if( !o.getLocked() )
        {
          o.fill( parseInt( this.getAttribute( 'value' ) ) );
        }
      }, this );
      
      html += ' onmouseover="Denbel.ui.StarBox.onMouseOver(this,' + this.index + ');"';
      
      YAHOO.util.Event.addListener( imageElement, 'mouseout', function( e, o )
      {
        YAHOO.util.Event.stopEvent( e );

        if( !o.getLocked() )
        {
          o.reset();
        }
      }, this );
      
      html += ' onmouseout="Denbel.ui.StarBox.onMouseOut(this,' + this.index + ');"';
      
      YAHOO.util.Event.addListener( imageElement, 'click', function( e, o )
      {
        YAHOO.util.Event.stopEvent( e );
        
        if( !o.getLocked() )
        {
          o.setValue( parseInt( this.getAttribute( 'value' ) ) );
          o.submit( parseInt( this.getAttribute( 'value' ) ) );
        }
      }, this );
      
      html += ' onclick="Denbel.ui.StarBox.onClick(this,' + this.index + ');"';
    }
    else
    {
      YAHOO.util.Event.removeListener( imageElement, 'click' );
      YAHOO.util.Event.removeListener( imageElement, 'mouseover' );
      YAHOO.util.Event.removeListener( imageElement, 'mouseout' );
    }
    
    return html;
  },
  
  /**
   * Sets all images to open
   * @return void
   */
  clear: function()
  {
    if( !this.objects || this.objects.length == 0 )
    {
      return;
    }
    
    var id = null;
    
    for( var i = 0; i < this.objects.length; i++ )
    {
      id = this.objects[i].getAttribute( 'id' );
      YAHOO.util.Dom.removeClass( YAHOO.util.Dom.get( id ), 'dbl-starbox-image-fill' );
      YAHOO.util.Dom.removeClass( YAHOO.util.Dom.get( id ), 'dbl-starbox-image-half' );
      YAHOO.util.Dom.addClass( YAHOO.util.Dom.get( id ), 'dbl-starbox-image' );
    }
  },
  
  /**
   * Fills the device with the given number of elements
   * @param int size
   * @return void
   */
  fill: function( size )
  {
    if( !this.objects || this.objects.length == 0 )
    {
      return;
    }
  
    if( !size || !YAHOO.lang.isNumber( size ) )
    {
      size = this.value;
    }
  
    var id = null;
  
    for( var i = 0; i < this.objects.length; i++ )
    {
      id = this.objects[i].getAttribute( 'id' );
      
      if( i < size )
      {
        YAHOO.util.Dom.removeClass( YAHOO.util.Dom.get( id ), 'dbl-starbox-image-half' );
        YAHOO.util.Dom.removeClass( YAHOO.util.Dom.get( id ), 'dbl-starbox-image' );
        YAHOO.util.Dom.addClass( YAHOO.util.Dom.get( id ), 'dbl-starbox-image-fill' );
      }
      else
      {
        YAHOO.util.Dom.removeClass( YAHOO.util.Dom.get( id ), 'dbl-starbox-image-fill' );
        YAHOO.util.Dom.removeClass( YAHOO.util.Dom.get( id ), 'dbl-starbox-image-half' );
        YAHOO.util.Dom.addClass( YAHOO.util.Dom.get( id ), 'dbl-starbox-image' );
      }
    }
  },
  
  /**
   * Resets the object
   * @param bool toInitial set to true to reset the value of the object to its initial value
   * @return void
   */
  reset: function( toInitial )
  {
    if( toInitial )
    {
      this.value = this.config.initialValue;
    }
    
    this.render();
  },
  
  /**
   * Submits the value of the device to the server
   * @param int value the value to post
   * @return bool
   */
  submit: function( value )
  {
    if( !YAHOO.lang.isNumber( value ) )
    {
      YAHOO.log( 'Value to submit is not a number', 'error', 'Denbel.ui.StarBox' );
      return false;
    }
    
    var rpc = new Denbel.rpc.XmlRpcClient( this.config.postUrl );
    var msg = rpc.createMessage( this.config.postMessage );

    for( var i = 0; i < this.config.postParameters.length; i++ )
    {
      msg.createAndAddParameter( this.config.postParameters[i] );
    }

    msg.createAndAddParameter( value );
    
    rpc.callService( msg,
    {
      success: function( res )
      {
        res.argument.object.setValue( res.data[0] );
        res.argument.object.config.callback.success.call( this, res );
      },
      failure: function( res )
      {
        //res.argument.object.reset( true );
        res.argument.object.config.callback.failure.call( this, res );
      },
      argument:
      {
        object: this
      }
    } );
    
    return true;
  },
  
  /**
   * Converts this object to its string representation
   * @return string
   */
  toString: function()
  {
    return 'Denbel.ui.StarBox, ' + this.id + ', ' + this.index;
  }
};

