#include "TestFramework.h"
#include "htio2/Kmer.h"

#include <limits>

using namespace htio2;
using namespace std;

typedef uint16_t KmerType;

void TestFramework::content()
{
    IS(ENCODED_NT5_A, 0);
    IS(ENCODED_NT5_T, 4);
    IS(ENCODED_NT5_G, 1);
    IS(ENCODED_NT5_C, 3);
    IS(ENCODED_NT5_N, 2);

    IS(encode_nt5('N'), ENCODED_NT5_N);
    IS(encode_nt5('A'), ENCODED_NT5_A);
    IS(encode_nt5('T'), ENCODED_NT5_T);
    IS(encode_nt5('G'), ENCODED_NT5_G);
    IS(encode_nt5('C'), ENCODED_NT5_C);
    IS(encode_nt5('Z'), ENCODED_ERROR);
    IS(encode_nt5('B'), ENCODED_ERROR);

    IS(decode_nt5(ENCODED_NT5_N), 'N');
    IS(decode_nt5(ENCODED_NT5_A), 'A');
    IS(decode_nt5(ENCODED_NT5_T), 'T');
    IS(decode_nt5(ENCODED_NT5_G), 'G');
    IS(decode_nt5(ENCODED_NT5_C), 'C');

    // encode
    EncodedSeq enc;
    encode_nt5("ATGXCNTA", enc);
    IS(enc.size(), 8);
    IS(enc[0], ENCODED_NT5_A);
    IS(enc[1], ENCODED_NT5_T);
    IS(enc[2], ENCODED_NT5_G);
    IS(enc[3], ENCODED_ERROR);
    IS(enc[4], ENCODED_NT5_C);
    IS(enc[5], ENCODED_NT5_N);
    IS(enc[6], ENCODED_NT5_T);
    IS(enc[7], ENCODED_NT5_A);

    {
        // generate kmer
        vector<KmerType> kmers;
        OK(gen_kmer_nt5(enc, kmers, 3));
        IS(kmers.size(), 6);
        IS(kmers[0], ENCODED_NT5_A + ENCODED_NT5_T*5 + ENCODED_NT5_G*5*5);
        IS(kmers[1], numeric_limits<KmerType>::max());
        IS(kmers[2], numeric_limits<KmerType>::max());
        IS(kmers[3], numeric_limits<KmerType>::max());
        IS(kmers[4], ENCODED_NT5_C + ENCODED_NT5_N*5 + ENCODED_NT5_T*5*5);
        IS(kmers[5], ENCODED_NT5_N + ENCODED_NT5_T*5 + ENCODED_NT5_A*5*5);

        // decode kmer
        IS(decode_kmer_nt5(kmers[0], 3), "ATG");
        IS(decode_kmer_nt5(kmers[1], 3), "");
        IS(decode_kmer_nt5(kmers[2], 3), "");
        IS(decode_kmer_nt5(kmers[3], 3), "");
        IS(decode_kmer_nt5(kmers[4], 3), "CNT");
        IS(decode_kmer_nt5(kmers[5], 3), "NTA");
    }

    {
        vector<KmerType> kmers;
        OK(gen_kmer_nt5(enc, kmers, 6));
        IS(kmers.size(), 3);

        KmerType kmer =
                ENCODED_NT5_A +
                ENCODED_NT5_T *5 +
                ENCODED_NT5_G *5*5 +
                ENCODED_NT5_C *5*5*5 +
                ENCODED_NT5_N *5*5*5*5 +
                ENCODED_NT5_T *5*5*5*5*5 ;
        IS(gen_kmer_nt5<KmerType>("ATGCNT"), kmer);
    }

    {
        vector<KmerType> kmers;
        OK(!gen_kmer_nt5(enc, kmers, 7));
        IS(kmers.size(), 0);

        IS(gen_kmer_nt5<KmerType>("ATGCNTT"), numeric_limits<KmerType>::max());
    }

    // decode
    {
        string dec;
        decode_nt5(enc, dec);
        IS(dec, "ATGNCNTA");
    }
}
