#include "eq_interleaver.h"

EQ_Interleaver::EQ_Interleaver()
{
}

EQ_Interleaver::EQ_Interleaver(int length, bool tail)
{
    set_interleaver_length(length, tail);
}

void EQ_Interleaver::set_interleaver_length(int length, bool tail)
{
    frame_length = length;
    if (tail)
        uncoded_bits_length = (int) (length - 6)/3;
}

void EQ_Interleaver::generate_interleaver()
{
    int len = frame_length;

    ivec odd_interleaver = to_ivec(linspace(0,len/2-1,len/2)*2);
    ivec even_interleaver = to_ivec(linspace(0,len/2-1,len/2)*2+1);
    Sequence_Interleaver<int> component_interleaver(odd_interleaver.length());
    component_interleaver.randomize_interleaver_sequence();
    odd_interleaver = component_interleaver.interleave(odd_interleaver);
    component_interleaver.randomize_interleaver_sequence();
    even_interleaver = component_interleaver.interleave(even_interleaver);

    interleaver_index = concat(odd_interleaver, even_interleaver);
    for (int i=0; i<len/2; i++)
    {
        interleaver_index(i*2) = even_interleaver(i);
        interleaver_index(i*2+1) = odd_interleaver(i);
    }
}

vec EQ_Interleaver::interleave(vec a, vec b, vec c, bool tail)
{           
    vec d= concat(a,b.left(a.length()),c.left(a.length()));

    frame_interleaver.set_interleaver_depth(d.length());
    frame_interleaver.set_interleaver_sequence(interleaver_index);
    vec e = frame_interleaver.interleave(d);
    vec interleaved_d = concat(e,b.right(3),c.right(3));

    return interleaved_d;
}

vec EQ_Interleaver::interleave(vec d, bool tail)
{
    vec a = d.left(uncoded_bits_length);
    vec b = d.mid(uncoded_bits_length, uncoded_bits_length+3);
    vec c = d.right(uncoded_bits_length+3);

    d= concat(a,b.left(a.length()),c.left(a.length()));

    frame_interleaver.set_interleaver_depth(d.length());
    frame_interleaver.set_interleaver_sequence(interleaver_index);
    vec e = frame_interleaver.interleave(d);
    vec interleaved_d = concat(e,b.right(3),c.right(3));

    return interleaved_d;
}

void EQ_Interleaver::deinterleave(vec interleaved_d, vec &a, vec &b, vec &c)
{
    vec tail = interleaved_d.right(6);
    vec tail_c = tail.right(3);
    vec tail_b = tail.left(3);

    interleaved_d.del(interleaved_d.length()-6, interleaved_d.length()-1);
    vec d = frame_interleaver.deinterleave(interleaved_d);

    a = d.left(d.length()/3);
    b = d.mid(a.length(),a.length());
    c = d.right(d.length()/3);

    b = concat(b,tail_b);
    c = concat(c,tail_c);
}

vec EQ_Interleaver::deinterleave(vec interleaved_d)
{
    vec tail = interleaved_d.right(6);
    vec tail_c = tail.right(3);
    vec tail_b = tail.left(3);

    interleaved_d.del(interleaved_d.length()-6, interleaved_d.length()-1);
    vec d = frame_interleaver.deinterleave(interleaved_d);

    vec a = d.left(d.length()/3);
    vec b = d.mid(a.length(),a.length());
    vec c = d.right(d.length()/3);

    b = concat(b,tail_b);
    c = concat(c,tail_c);

    vec deinterleaved_d = concat(a,b,c);
    return deinterleaved_d;
}

ivec EQ_Interleaver::get_interleaver()
{
    return interleaver_index;
}
