//     HTIO - a high-throughput sequencing reads input/output library
//
//     This program is free software: you can redistribute it and/or modify
//     it under the terms of the GNU General Public License as published by
//     the Free Software Foundation, either version 3 of the License, or
//     (at your option) any later version.
//
//     This program is distributed in the hope that it will be useful,
//     but WITHOUT ANY WARRANTY; without even the implied warranty of
//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//     GNU General Public License for more details.
//
//     You should have received a copy of the GNU General Public License
//     along with this program.  If not, see <http://www.gnu.org/licenses/>.

#include "htio2/FastqIO.h"
#include "htio2/FastqSeq.h"
#include "htio2/Error.h"
#include "htio2/FileHandle.h"
#include <zlib.h>

using namespace std;

namespace htio2
{

FastqIO::FastqIO(const string& file, IOMode mode, CompressFormat comp) : SeqIO(file, mode, comp)
{
}

FastqIO::FastqIO(FileHandle* handle) : SeqIO(handle)
{
}

FastqIO::FastqIO(FILE* handle, bool auto_close) : SeqIO(handle, auto_close)
{
}

FastqIO::FastqIO(gzFile handle, bool auto_close) : SeqIO(handle, auto_close)
{
}

FastqIO::~FastqIO()
{
}

bool FastqIO::next_seq(FastqSeq& output)
{
    return read_one_seq(output.id, output.desc, output.seq, output.quality);
}

bool FastqIO::next_seq(SimpleSeq& output)
{
    static std::string null;
    return read_one_seq(output.id, output.desc, output.seq, null);
}

void FastqIO::write_seq(const FastqSeq& seq)
{
    handle->write_line("@" + seq.id + " " + seq.desc);
    handle->write_line(seq.seq);
    handle->write_line("+");
    handle->write_line(seq.quality);
}

void FastqIO::write_seq(const SimpleSeq& seq)
{
    handle->write_line("@" + seq.id + " " + seq.desc);
    handle->write_line(seq.seq);
    handle->write_line("+");
    handle->write_line(std::string(seq.length(), 'I'));
}

bool FastqIO::read_one_seq(std::string& id, std::string& desc, std::string& seq, std::string& qual)
{
    int32_t line_got = 0;

    while (1)
    {
        bool re = handle->read_line(buffer);


        if (!re) break;

        if (line_got == 0)
        {
            if (buffer.length() == 0) continue;
            line_got++;

            size_t first_space = buffer.find_first_of(" \t");
            size_t desc_begin = buffer.find_first_not_of(" \t", first_space);
            id.assign(buffer, 1, first_space - 1);

            if (desc_begin == string::npos)
                desc = "";
            else
                desc.assign(buffer, desc_begin, string::npos);
        }
        else if (line_got == 1)
        {
            line_got++;
            seq = buffer;
        }
        else if (line_got == 2)
        {
            line_got++;
            if (buffer[0] != '+')
                throw InvalidFileContent(buffer, handle->tell());
        }
        else if (line_got == 3)
        {
            line_got++;
            qual = buffer;
            if (seq.length() != buffer.length())
                throw InvalidFileContent(buffer, handle->tell());
            break;
        }
    }

    if ((line_got != 4) && (line_got != 0))
        throw InvalidFileContent("incomplete FASTQ record", handle->tell());

    return line_got > 0;
}

} // namespace htio2
