//     HTQC - a high-throughput sequencing quality control toolkit
//
//     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 "htqc/BaseQualCounter.h"
#include "htio2/QualityUtil.h"

using namespace htqc;
using namespace std;

BaseCounter& BaseCounter::operator+=(const htqc::BaseCounter& other)
{
    a += other.a;
    t += other.t;
    g += other.g;
    c += other.c;
    n += other.n;
    mask += other.mask;
    return *this;
}

TileQualCounter& TileQualCounter::operator+=(const htqc::TileQualCounter& other)
{
    num_reads_10 += other.num_reads_10;
    num_reads_10_20 += other.num_reads_10_20;
    num_reads_20_30 += other.num_reads_20_30;
    num_reads_30 += other.num_reads_30;
    return *this;
}

BaseQualCounter::BaseQualCounter(htio2::QualityEncode encode)
: key_max(-1)
, from(-1)
, to(-1)
{
    htio2::get_quality_range(encode, from, to);
    key_max = to - from;
    counter.resize(key_max + 1, 0);
}

void BaseQualCounter::create_chart(BaseQualBoxChart& chart) const
{
    long num_seq = 0;
    for (int qual = from; qual <= to; qual++)
    {
        num_seq += get_num(qual);
    }

    long i_dec_low = num_seq / 10;
    long i_quat_low = num_seq / 4;
    long i_median = num_seq / 2;
    long i_quat_high = num_seq * 3 / 4;
    long i_dec_high = num_seq * 9 / 10;

    long seq_sum = 0;
    long qual_sum = 0;
    for (int qual = from; qual <= to; qual++)
    {
        long num = get_num(qual);
        long seq_sum_next = seq_sum + num;
        qual_sum += qual*num;

        if (seq_sum < i_dec_low && i_dec_low <= seq_sum_next)
        {
            chart.dec_low = qual;
        }
        if (seq_sum < i_quat_low && i_quat_low <= seq_sum_next)
        {
            chart.quat_low = qual;
        }
        if (seq_sum < i_median && i_median <= seq_sum_next)
        {
            chart.median = qual;
        }
        if (seq_sum < i_quat_high && i_quat_high <= seq_sum_next)
        {
            chart.quat_high = qual;
        }
        if (seq_sum < i_dec_high && i_dec_high <= seq_sum_next)
        {
            chart.dec_high = qual;
        }

        seq_sum = seq_sum_next;
    }

    if (num_seq == 0)
        chart.mean = 0;
    else
        chart.mean = double(qual_sum) / double(num_seq);
}

BaseQualCounter& BaseQualCounter::operator+=(const htqc::BaseQualCounter& other)
{
    for (int i = 0; i < other.counter.size(); i++)
    {
        counter[i] += other.counter[i];
    }
    return *this;
}
