/*!
 * Base64 class
 * @version 1.0
 * @author M.F.Endenburg
 * @copyright (c) Denbel Systems, 2008
 */

// load namespace
Denbel.load( 'core.Base64' );

/**
 * Base64 class
 */
Denbel.core.Base64 =
{
    /**
     * key strings
     * @var string
     */
    _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

  /**
   * Encodes a string to base64
   * @param string
   * @return string
   */
  encode: function( input )
  {
      var output = "";
      var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
      var i = 0;

      input = Denbel.core.Base64._utf8_encode( input );

      while( i < input.length )
      {
          chr1 = input.charCodeAt( i++ );
          chr2 = input.charCodeAt( i++ );
          chr3 = input.charCodeAt( i++ );

          enc1 = chr1 >> 2;
          enc2 = ( ( chr1 & 3 ) << 4 ) | ( chr2 >> 4 );
          enc3 = ( ( chr2 & 15 ) << 2 ) | ( chr3 >> 6 );
          enc4 = chr3 & 63;

          if( isNaN( chr2 ) )
          {
              enc3 = enc4 = 64;
          }
          else if( isNaN( chr3 ) )
          {
              enc4 = 64;
          }

          output = output + this._keyStr.charAt( enc1 ) + this._keyStr.charAt( enc2 ) + this._keyStr.charAt( enc3 ) + this._keyStr.charAt( enc4 );
      }

      return output;
  },

  /**
   * Decodes a base64 value
   * @param string
   * @return string
   */
  decode: function( input )
  {
      var output = "";
      var chr1, chr2, chr3;
      var enc1, enc2, enc3, enc4;
      var i = 0;

      input = input.replace( /[^A-Za-z0-9\+\/\=]/g, "" );

      while( i < input.length )
      {
          enc1 = this._keyStr.indexOf( input.charAt( i++ ) );
          enc2 = this._keyStr.indexOf( input.charAt( i++ ) );
          enc3 = this._keyStr.indexOf( input.charAt( i++ ) );
          enc4 = this._keyStr.indexOf( input.charAt( i++ ) );

          chr1 = ( enc1 << 2 ) | ( enc2 >> 4 );
          chr2 = ( ( enc2 & 15 ) << 4 ) | ( enc3 >> 2 );
          chr3 = ( ( enc3 & 3 ) << 6 ) | enc4;

          output = output + String.fromCharCode( chr1 );

          if( enc3 != 64 )
          {
              output = output + String.fromCharCode( chr2 );
          }
          if( enc4 != 64 )
          {
              output = output + String.fromCharCode( chr3 );
          }

      }

      output = Denbel.core.Base64._utf8_decode( output );

      return output;

  },

  /**
   * Encodes a string to UTF-8
   * @param string
   * @return string
   */
  _utf8_encode: function( string )
  {
      string = string.replace( /\r\n/g, "\n" );
      var utftext = "";

      for( var n = 0; n < string.length; n++ )
      {
          var c = string.charCodeAt( n );

          if( c < 128 )
          {
              utftext += String.fromCharCode( c );
          }
          else if( ( c > 127 ) && ( c < 2048 ) )
          {
              utftext += String.fromCharCode( ( c >> 6 ) | 192 );
              utftext += String.fromCharCode( ( c & 63 ) | 128 );
          }
          else
          {
              utftext += String.fromCharCode( ( c >> 12 ) | 224 );
              utftext += String.fromCharCode( ( ( c >> 6 ) & 63 ) | 128 );
              utftext += String.fromCharCode( ( c & 63 ) | 128 );
          }

      }

      return utftext;
  },

  /**
   * Decodes an UTF-8 string
   * @param string
   * @return string
   */
  _utf8_decode: function( utftext )
  {
      var string = "";
      var i = 0;
      var c = c1 = c2 = 0;

      while ( i < utftext.length )
      {
          c = utftext.charCodeAt( i );

          if( c < 128 )
          {
              string += String.fromCharCode( c );
              i++;
          }
          else if( ( c > 191 ) && ( c < 224 ) )
          {
              c2 = utftext.charCodeAt( i + 1 );
              string += String.fromCharCode( ( ( c & 31 ) << 6 ) | ( c2 & 63 ) );
              i += 2;
          }
          else
          {
              c2 = utftext.charCodeAt( i + 1 );
              c3 = utftext.charCodeAt( i + 2 );
              string += String.fromCharCode( ( ( c & 15 ) << 12 ) | ( ( c2 & 63 ) << 6 ) | ( c3 & 63 ) );
              i += 3;
          }

      }

      return string;
  }
};
