#include "TestFramework.h"
#include "TestConfig.h"

#include "htio2/FastqIO.h"
#include "htio2/PairedEndIO.h"
#include "htio2/FastqSeq.h"

#include <map>

using namespace std;
using namespace htio2;
using namespace htio2::juce;

void parse_fields(const string& desc, map<string, int>& result)
{
    StringArray tokens;
    tokens.addTokens(String(desc), " =", "");
    if (tokens.size() % 2)
    {
        fprintf(stderr, "invalid token size %d, not even\n", tokens.size());
        abort();
    }
    for (int i = 0; i < tokens.size(); i+=2)
    {
        const String& key = tokens[i];
        const String& value = tokens[i+1];
        result[key.toStdString()] = value.getIntValue();
    }
}

void TestFramework::content()
{
    const char* cmd = "../src/ht2-overlap -q -i " TEST_SOURCE_DIR "/test1.fastq.gz " TEST_SOURCE_DIR "/test2.fastq.gz -o ovlp -u novlp";
    ok(!system(cmd), cmd);


    map<string,string> ovlp_seqs;
    map<string,int> offsets;
    {
        htio2::FastqIO fh_ovlp("ovlp.fastq.gz", htio2::READ);
        htio2::FastqSeq seq;
        while (fh_ovlp.next_seq(seq))
        {
            map<string,int> attrs;
            parse_fields(seq.desc, attrs);
            if (!attrs.count("kmer_pos_a"))
            {
                fprintf(stderr, "no attribute kmer_pos_a\n");
                abort();
            }
            if (!attrs.count("kmer_pos_b"))
            {
                fprintf(stderr, "no attribute kmer_pos_b\n");
                abort();
            }

            ovlp_seqs[seq.id] = seq.seq;
            offsets[seq.id] = attrs["kmer_pos_b"] - attrs["kmer_pos_a"];
        }
    }

    {
        htio2::FastqSeq seq1;
        htio2::FastqSeq seq2;
        htio2::PairedEndIO fh_in(TEST_SOURCE_DIR "/test1.fastq.gz", TEST_SOURCE_DIR "/test2.fastq.gz",
                                 htio2::READ);
        while (fh_in.next_pair(seq1,seq2))
        {
            if (seq1.id != seq2.id)
            {
                fprintf(stderr, "conflict ID: %s and %s\n", seq1.id.c_str(), seq2.id.c_str());
                abort();
            }

            if (!ovlp_seqs.count(seq1.id))
                continue;

            const string& merged_seq = ovlp_seqs[seq1.id];
            int offset = offsets[seq1.id];

            for (int i = 0; i < merged_seq.length(); i++)
            {
                int i1 = numeric_limits<int>::max();
                int i2 = numeric_limits<int>::max();

                if (offset >= 0)
                {
                    i1 = i - offset;
                    i2 = i;
                }
                else
                {
                    i1 = i;
                    i2 = i + offset;
                }

                if (0 <= i1 && i1 < seq1.length())
                {
                    if (0 <= i2 && i2 < seq2.length())
                    {
                        if (seq1.quality[i1] >= seq2.quality[i2])
                            IS(seq1.seq[i1], merged_seq[i]);
                        else
                            IS(seq2.seq[i2], merged_seq[i]);
                    }
                    else
                    {
                        IS(seq1.seq[i1], merged_seq[i]);
                    }
                }
                else
                {
                    if (0 <= i2 && i2 < seq2.length())
                    {
                        IS(seq2.seq[i2], merged_seq[i]);
                    }
                    else
                    {
                        fprintf(stderr, "invalid position %d and %d at %d", i1, i2, i);
                        abort();
                    }
                }
            }
        }
    }
}
