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

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

#include "htio2/JUCE-3.0.8/JuceHeader.h"

#include <vector>
#include <map>

using namespace std;
using namespace htio2::juce;

#define FILE1 TEST_SOURCE_DIR "/test1.fastq.gz"
#define FILE2 TEST_SOURCE_DIR "/test2.fastq.gz"
#define BARCODE TEST_SOURCE_DIR "/barcodes.tab"

typedef map<string, pair<string,string> > BarcodeMap;

void read_barcode(BarcodeMap& barcodes)
{
    htio2::PlainFileHandle fh_barcode(BARCODE, htio2::READ);
    string line;

    while (fh_barcode.read_line(line))
    {
        size_t tab1 = line.find_first_of('\t');
        if (tab1 == string::npos)
        {
            cerr << "line contain no TAB" << endl
                 << line << endl;
            exit(EXIT_FAILURE);
        }

        size_t tab2 = line.find_first_of('\t', tab1+1);
        if (tab2 == string::npos)
        {
            cerr << "line contain no 2nd TAB" << endl
                 << line << endl;
            exit(EXIT_FAILURE);
        }

        string proj(line.substr(0, tab1));
        string sample(line.substr(tab1 + 1, tab2 - tab1 - 1));
        string barcode(line.substr(tab2 + 1));

        barcodes.insert(make_pair(barcode, make_pair(proj, sample)));
    }

}

void TestFramework::content()
{
    const char* cmd =
            "../src/ht2-demul -q -P"
            " -i " FILE1 " " FILE2
            " --barcode " BARCODE
            " -o demul";
    ok(!system(cmd), cmd);

    BarcodeMap barcodes;
    read_barcode(barcodes);

    File dir_out("demul");
    size_t n_seq = 0;

    // traverse projects
    Array<File> dirs_project;
    dir_out.findChildFiles(dirs_project, File::findDirectories, false);

    htio2::FastqSeq seq;

    for (int i_proj = 0; i_proj < dirs_project.size(); i_proj++)
    {
        const File& dir_proj = dirs_project[i_proj];
        String proj_name = dir_proj.getFileName();

        Array<File> seq_files;
        dir_proj.findChildFiles(seq_files, File::findFiles, false);

        for (int i_file = 0; i_file < seq_files.size(); i_file++)
        {
            const File& seq_file = seq_files[i_file];
            String file_base = seq_file.getFileName();
            int i_suffix = file_base.indexOf(".fastq");
            String sample_name = file_base.substring(0, i_suffix-2);

            // check the content of this file
            htio2::FastqIO fh(seq_file.getFullPathName().toStdString(), htio2::READ);
            while (fh.next_seq(seq))
            {
                n_seq++;
                string barcode = seq.desc.substr(seq.desc.find_last_of(':')+1);
                BarcodeMap::iterator it_barcode = barcodes.find(barcode);
                ok(it_barcode != barcodes.end(), (barcode + " barcode exist").c_str());
                const string& barcode_proj = it_barcode->second.first;
                const string& barcode_sample = it_barcode->second.second;

                IS(file_base[i_suffix-1], seq.desc[0]);
                is(barcode_proj,   proj_name.toStdString(),   ("project " + barcode_proj + " is " + proj_name.toStdString()).c_str());
                is(barcode_sample, sample_name.toStdString(), ("sample " + barcode_sample + " is " + sample_name.toStdString()).c_str());
            }
        }
    }

    // traverse demul failed files
    Array<File> files_fail;
    dir_out.findChildFiles(files_fail, File::findFiles, false, "demul_failed*.fastq.gz");
    IS(files_fail.size(), 2);

    for (int i_file = 0; i_file < files_fail.size(); i_file++)
    {
        htio2::FastqIO fh(files_fail[i_file].getFullPathName().toStdString(), htio2::READ);
        while (fh.next_seq(seq))
        {
            n_seq++;
            string barcode = seq.desc.substr(seq.desc.find_last_of(':')+1);
            BarcodeMap::iterator it = barcodes.find(barcode);
            ok(it == barcodes.end(), (barcode + " unknown").c_str());
        }
    }

    IS(n_seq, 200);
}
