/**
 * @file PAT.cpp
 *
 */

#include "mpeg2/ts/PAT.h"

namespace MPEG2
{
namespace TS
{

PAT::PAT()
{
    _programs = NULL;
    reset();
}

PAT::PAT(const PAT &pat)
{
    _table_id                 = pat._table_id;
    _section_syntax_indicator = pat._section_syntax_indicator;
    _section_length           = pat._section_length;
    _transport_stream_id      = pat._transport_stream_id;
    _version_number           = pat._version_number;
    _current_next_indicator   = pat._current_next_indicator;
    _section_number           = pat._section_number;
    _last_section_number      = pat._last_section_number;
    _program_count            = pat._program_count;
    _programs = (struct _program *)malloc(sizeof(uint16_t) * 2 * _program_count);
    for (int i = 0; i < _program_count; ++i)
    {
        _programs[i]._program_number = pat._programs[i]._program_number;
        _programs[i]._pid            = pat._programs[i]._pid;
    }
}

PAT::~PAT()
{
    reset();
}

bool PAT::decode_section()
{
    bool result = true;
    _table_id = _section[0x00];
    if (_table_id == TABLE_ID_PAT)
    {
        _section_syntax_indicator = (_section[0x01] & 0x80) >> 7;
        _section_length           = ((_section[0x01] << 8) + _section[0x02]) & 0x0FFF;
        _transport_stream_id      = (_section[0x03] << 8) + _section[0x04];
        _version_number           = (_section[0x05] & 0x3E) >> 1;
        _current_next_indicator   = _section[0x05] & 0x01;
        _section_number           = _section[0x06];
        _last_section_number      = _section[0x07];
        _program_count            = (_section_length - 9) / 4;
        if (_programs != NULL)
        {
            free(_programs);
        }
        _programs = (struct _program *)malloc(sizeof(uint16_t) * 2 * _program_count);
        for (int i = 0; i < _program_count; ++i)
        {
            _programs[i]._program_number = (_section[0x08 + i * 4] << 8) + _section[0x09 + i * 4];
            _programs[i]._pid            = ((_section[0x0A + i * 4] << 8) + _section[0x0B + i * 4]) & 0x1FFF;
        }
    }
    else
    {
        reset();
        result = false;
    }
    return result;
}

void PAT::reset()
{
    _table_id                 = 0;
    _section_syntax_indicator = 0;
    _section_length           = 0;
    _transport_stream_id      = 0;
    _version_number           = 0;
    _current_next_indicator   = 0;
    _section_number           = 0;
    _last_section_number      = 0;
    _program_count            = 0;
    if (_programs != NULL)
    {
        free(_programs);
        _programs = NULL;
    }
}

bool PAT::isEqual(PAT *pat)
{
    bool result = false;
    if (pat != NULL)
    {
        if (_program_count == pat->_program_count)
        {
            if ((_programs != NULL) && (pat->_programs != NULL))
            {
                result = (memcmp(_programs, pat->_programs, sizeof(uint16_t) * 2 * _program_count) == 0);
            }
        }
    }
    return result;
}

} // TS
} // MPEG2
