
function iw_rotor_encode(base64_array, rotor)
{
    var encoded = new Array();
    var runner = 7;

    for (var i = 0; i < base64_array.length; i++) 
    {
        if(base64_array[i] == -1)
        {
            encoded[i] = base64_array[i];
        }
        else 
        {
            encoded[i] = ((base64_array[i] + rotor + runner) % 64);
        }
        runner = (runner + 1) % 64;
    }
    return encoded;
}


function iw_base64_byte_to_base64_char(b)
{
    if(b > 63 || b < 0)
    {
        alert('Invalid base64 byte '+b);
        return '?';
    }
    else 
    {
        return ('ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
                'abcdefghijklmnopqrstuvwxyz' +
                '0123456789._').charAt(b);
        
    }
}


function iw_base64_character_encode(base64_array)
{
    var encoded = '';
    for(var i = 0; i < base64_array.length; i++) 
    {
        if(base64_array[i] == -1)
        {
            encoded += '=';
        } 
        else
        {
            encoded += iw_base64_byte_to_base64_char(base64_array[i]);
        }
    }
    return encoded;
}


function iw_base64_encode(ascii_array)
{
    var encoded = new Array();
    for(var i = 0; i < ascii_array.length; i += 3)
    {
        var block = 0;
        var slack = ascii_array.length - i -1;
        var end = (slack >= 2) ? 2 : slack;
        for(var block_index = 0; block_index <= end; block_index++)
        {
            var b = ascii_array[i + block_index];
            var neuter = (b < 0) ? b + 256 : b;
            block += neuter << (8 * (2 - block_index));
        } 
        
        for(var j = 0; j < 4; j++)
        { 
            var sixbit = (block >>> (6 * (3 - j))) & 0x3f;
            encoded[(4*i/3) + j] = sixbit;
        }
        if(slack < 1)
        { 
            encoded[(4*i/3) + 2] = -1;
        } 
        if(slack < 2)
        { 
            encoded[(4*i/3) + 3] = -1;
        } 
    } 
    return encoded;
} 


function iw_ascii_encode(str)
{
    var ascii_encoded = new Array();
    for(var i = 0; i < str.length; i++)
    {
      ascii_encoded[i] = str.charCodeAt(i);
    }
    return ascii_encoded;
}


function iw_checksum_encode(str)
{
    var checksum = 0;
    for(var i = 0; i < str.length; i++)
    {
        checksum += str.charCodeAt(i);
    }
    return iw_base64_byte_to_base64_char(checksum%64) + str;
}


function iw_encode(str, rotor)
{
    var ascii = iw_ascii_encode(str);
    var base64 = iw_base64_encode(ascii);
    var rotor_base64 = iw_rotor_encode(base64, rotor);
    var base64_chars = iw_base64_character_encode(rotor_base64);
    var checksummed_rotor_base64_chars = iw_checksum_encode(base64_chars);
    return checksummed_rotor_base64_chars;
}

