/*
 * charCounter
 * 
 * Displays a counter with the remaining text. 
 * 
 * Example:
 *   $('#description').charCounter(
 *   {
 *     limit: 140,
 *     counter: '#textcounter',
 *   
 *     okSize: 140,
 *     okStyle: '.ok',
 *   
 *     watchSize: 20,
 *     watchStyle: '.watch',
 *   
 *     warningSize: 10,
 *     warningStyle: '.warning',
 *   
 *     errorSize: 0,
 *     errorStyle: '.error',
 *   });
 *
 * $Version: 2008-10-24
 * Copyright (c) 2008 Ali Karbassi
 * ali.karbassi@gmail.com
 * Source: http://tech.karbassi.com/2008/10/27/twitter-style-text-counter-in-jquery/
 *
 * Modified by: Mario J Vargas (angstrey@hotmail.com)
 * $Version: 2009-08-26
 * 
 * Example:
 *   // When counter ID not supplied (i.e. counter: '#textcounter')
 *   // text input control is automatically wrapped with text counter's HTML.
 *   $('#description').charCounter(
 *   {
 *		limit: 140,
 *   
 *		okSize: 140,
 *		okStyle: '.ok',
 *   
 *		watchSize: 20,
 *		watchStyle: '.watch',
 *   
 *		warningSize: 10,
 *		warningStyle: '.warning',
 *   
 *		errorSize: 0,
 *		errorStyle: '.error',
 *
 *      // You can also use a callback function to invoke whenever something
 *      // is entered into the textarea associated with the plugin.
 *      // Example application: in a classified ad, you want to display
 *      // a list of available ads by size. The size is dictated by the
 *      // number of characters in the ad. The more characters entered,
 *      // the less number of ad sizes that become available. Too many
 *      // characters (over limit above) will result in no ad sizes available.
 *      // The list of ads can be obtained through an Ajax call to a server
 *      // side script that accepts the number of characters entered so far
 *      // as an argument.
 *      
 *		callback: function( lengthSoFar, charsLeft ) { [code here] }
 *   });
*
 */
jQuery.fn.charCounter = function(options) {
   var curSize = $(this).val().length;
   var charsLeft = options['limit'] - curSize;
   var types = ['ok', 'watch', 'warning', 'error'];
   var x = {};

   // If a counter's ID hasn't been specified, 
   // automatically wrap the input control with the
   // HTML for the text counter.
   if( typeof( options['counter'] ) == 'undefined' )
   {
      var curElm = $(this);	// text input control

      var counterBlockID = "textcounter-block-" +  curElm.attr( "id" );
      var elmWrapper = "<div class='textcounter-block' id='" + counterBlockID + "'></div>"
      // Identity text input control as text counter's input control
      // and wrap the control with the HTML block. This allows us to
      // adjust the width of the input control via CSS.
      curElm.addClass( "textcounter-input" ).wrap( elmWrapper );

      // Now that the input control block has been wrapped with
      // a "textcounter block", inject the actual text counter's HTML
      var counterID = "textcounter-" + curElm.attr( "id" );
      var counterHtml = "<div class='textcounter-display'>" 
			+ "Character Count: <span class='textcounter-count' id='" + counterID + "_CharsSoFar'></span>&nbsp;&nbsp;"
			+ "Characters Remaining: <span class='textcounter-count' id='" + counterID + "'></span>" 
		+ "</div>";
      $( '#textcounter-block-' +  curElm.attr( "id" ) ).prepend( counterHtml );

      // Finally, add the missing counter ID to continue
      // normal execution of the charCounter
      options['counter'] = '#' + counterID;
   }
   
   $.each(types, function(){
      var el = this.toString();
      x[el] = {'Max' : options[el + 'Size'], 
      'Style' : options[el + 'Style'].substring(0, 1) == '.' || options[el + 'Style'].substring(0, 1) == '#' ? options[el + 'Style'].substring(1, options[el + 'Style'].length) : options[el + 'Style'], 
      'Type' : options[el + 'Style'].substring(0, 1) == '.' ? 'class' : 'id'}
   });

   for( var i=0; i < types.length; i++)
   {
      var el = types[i].toString();

      // Last Element check
      if( i+1 < types.length ) {
         var nextEl = types[i+1].toString();
         // console.debug(charsLeft, el, x[el]['Max'], x[nextEl]['Max']+1, charsLeft > x[nextEl]['Max'] && charsLeft < x[el]['Max'] + 1);
         if( charsLeft > x[nextEl]['Max'] && charsLeft < x[el]['Max'] + 1) {
            clean();
         }
      } else {
         // console.debug(charsLeft, el, x[el]['Max'], x[nextEl]['Max']+1, charsLeft < x[el]['Max'] + 1);
         if( charsLeft < x[el]['Max']  ) {
            clean();
         }
      }
   }
   
   $(options['counter']).text(charsLeft);
   $(options['counter']+"_CharsSoFar").text(curSize);
   
   if( options['callback'] )
      options['callback']( curSize, charsLeft );
   
   // Add an event so the counter updates when the user types.
   $(this).one('keyup', function(){
      $(this).charCounter(options);
   });
   
   
   function clean() {
      if( x[el]['Type'] == 'class' ) {
         $.each(types, function(){
            var temp = this.toString();
            if( $(options['counter']).hasClass(temp) ) {
               $(options['counter']).removeClass(temp);
            }
         });
         $(options['counter']).addClass(x[el]['Style']);
      } else {
         $(options['counter']).id(x[el]['Style']);
      }
   }
};
