
#include "transposition.hpp"
#include <iostream>

using namespace std;

Transposition::Transposition()
    :
    m_Verbose( false )
{
    // empty constructor, just used to initialize the verbose-flag
}

void Transposition::setVerbose( bool flag )
{
    m_Verbose = flag;
}

void Transposition::swap( char* a, char* b )
{
    char temp = *a;
    *a = *b;
    *b = temp;
}

void Transposition::swap( int* a, int* b )
{
    int temp = *a;
    *a = *b;
    *b = temp;
}

void Transposition::print()
{
    int width  = (int)m_Key.size();
    int height = (int)m_Data.size() / width;

    if( (int)m_Data.size() > (width*height) )
    {
        height++;
    }

    for( int x=0; x<width;  ++x )
    {
        m_Key[x] = toupper( m_Key[x] );
    }

    for( int x=0; x<width;  ++x )
    {
        cout << m_Key[x];
    }
    cout << endl;
    for( int x=0; x<width;  ++x )
    {
        cout << m_EncodeShift[x]%10;
    }
    cout << endl;
    for( int x=0; x<width;  ++x )
    {
        cout << (m_EncodeShift[x]/10)%10;
    }
    cout << endl;
    for( int x=0; x<width;  ++x )
    {
        cout << '-';
    }
    cout << endl;

    for( int y=0; y<height; ++y )
    {
        for( int x=0; x<width;  ++x )
        {
            if( (x+y*width) > (int)m_Data.size() )
            {
                break;
            }
            cout << m_Data[x+y*width];
        }
        cout << endl;
    }
    cout << endl;
}

void Transposition::setKey( std::string key )
{
    m_Key = key;

    m_EncodeShift.clear();
    m_EncodeShift.resize( m_Key.size() );

    m_DecodeShift.clear();
    m_DecodeShift.resize( m_Key.size() );

    for( int x=0; x<(int)m_Key.size();  ++x )
    {
        m_Key[x] = toupper( m_Key[x] );
    }

    for( unsigned int n=0; n<key.size(); n++ )
    {
        m_EncodeShift[n] = n;
        m_DecodeShift[n] = n;
    }

    for( int n = 0; n < (int)key.size(); ++n )
    for( int m = 0; m < ( (int)key.size() - 1 - n ); ++m )
    {
        if( key[m+1] < key[m] )
        {
            char temp = key[m];
            key[m] = key[m+1];
            key[m+1] = temp;
            swap( &m_EncodeShift[m], &m_EncodeShift[m+1] );
        }
    }

    if( m_Verbose )
    {
        m_Data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
                 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
                 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
                 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
                 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

        cout << endl;
        cout << "=====================================================" << endl;
        cout << "Transposition-table:" << endl << endl;
        print();
    }
}

std::string Transposition::encode( std::string s )
{
    m_Data = s;
    s.clear();

    int width  = (int)m_Key.size();
    int height = (int)m_Data.size() / width;

    if( (int)m_Data.size() > (width*height) )
    {
        height++;
    }

    for( int c=0; c<width; ++c )
    {
        int x = m_EncodeShift[c];
        for( int y=0; y<height; ++y )
        {
            if( (x+y*width) >= (int)m_Data.size() )
            {
                break;
            }
            s += m_Data[x+y*width];
        }
    }
    return( s );
}

std::string Transposition::decode( std::string s )
{
    int idx=0;
    int width  = (int)m_Key.size();
    int height = (int)s.size() / width;

    if( (int)s.size() > (width*height) )
    {
        height++;
    }

    m_Data.resize( s.size() );

    for( int c=0; c<width; ++c )
    {
        int x = m_EncodeShift[c];
        for( int y=0; y<height; ++y )
        {
            if( (x+y*width) >= (int)m_Data.size() )
            {
                continue;
            }
            m_Data[x+y*width] = s[idx];
            idx++;
        }
    }
    return( m_Data );
}

