/*
 *  Table.h
 */

#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

#include "mpeg2/ts/Header.h"

namespace MPEG2
{
namespace TS
{

static const int MAX_SECT_LEN = 4096;
static const int MAX_DESC_LEN =  255;

enum
{
    TABLE_ID_PAT = 0x00,
    TABLE_ID_PMT = 0x02
};

enum
{
    TAG_BOUQUET_NAME_DESCRIPTOR         = 0x47,
    TAG_SERVICE_DESCRIPTOR              = 0x48,
    TAG_SHORT_EVENT_DESCRIPTOR          = 0x4D,
    TAG_EXTENDED_EVENT_DESCRIPTOR       = 0x4E,
    TAG_COMPONENT_DESCRIPTOR            = 0x50,
    TAG_CONTENT_DESCRIPTOR              = 0x54,
    TAG_EVENT_GROUP_DESCRIPTOR          = 0xD6,
    TAG_DIGITAL_COPY_CONTROL_DESCRIPTOR = 0xC1,
    TAG_AUDIO_COMPONENT_DESCRIPTOR      = 0xC4,
    TAG_DATA_CONTENT_DESCRIPTOR         = 0xC7,
    TAG_SERIES_DESCRIPTOR               = 0xD5
};

// 6.2.1 Bouquet name descriptor
typedef struct _BouquetNameDescriptor
{
    uint8_t         _descriptor_tag;                        //  8
    uint8_t         _descriptor_length;                     //  8
    uint8_t         _descriptor[MAX_DESC_LEN];              //  8 x N
} BouquetNameDescriptor;

// 6.2.3 Component descriptor
typedef struct _ComponentDescriptor
{
    uint8_t         _descriptor_tag;                        //  8
    uint8_t         _descriptor_length;                     //  8
    uint8_t         _reserved_future_use;                   //  4
    uint8_t         _stream_content;                        //  4
    uint8_t         _component_type;                        //  8
    uint8_t         _component_tag;                         //  8
    uint8_t         _ISO_639_language_code[3];              //  24
    uint8_t         _text_char[MAX_DESC_LEN];               //  8 x N
} ComponentDescriptor;

// 6.2.4 Content descriptor
typedef struct _ContentDescriptor
{
    uint8_t         _descriptor_tag;                        //  8
    uint8_t         _descriptor_length;                     //  8
    struct
    {
        uint8_t     _content_nibble_level_1;                //  4
        uint8_t     _content_nibble_level_2;                //  4
        uint8_t     _user_nibble_1;                         //  4
        uint8_t     _user_nibble_2;                         //  4
    } _contents[MAX_DESC_LEN/2];                            // 16 x N
} ContentDescriptor;

// 6.2.7 Extended event descriptor
typedef struct _ExtendedEventDescriptor
{
    uint8_t         _descriptor_tag;                        //  8
    uint8_t         _descriptor_length;                     //  8
    uint8_t         _descriptor_number;                     //  4
    uint8_t         _last_descriptor_number;                //  4
    uint8_t         _ISO_639_language_code[3];              // 24
    uint8_t         _length_of_items;                       //  8
    uint8_t         _item_count;
    struct
    {
        uint8_t     _item_description_length;               //  8
        uint8_t     _item_description[MAX_DESC_LEN];        //  8 x N
        uint8_t     _item_length;                           //  8
        uint8_t     _item[MAX_DESC_LEN];                    //  8 x N
    } _items[MAX_DESC_LEN/2];
    uint8_t         _text_length;                           //  8
    uint8_t         _text[MAX_DESC_LEN];                    //  8 x N
} ExtendedEventDescriptor;

// 6.2.13 Service descriptor
typedef struct _ServiceDescriptor
{
    uint8_t         _descriptor_tag;                        //  8
    uint8_t         _descriptor_length;                     //  8
    uint8_t         _service_type;                          //  8
    uint8_t         _service_provider_name_length;          //  8
    uint8_t         _service_provider_name[MAX_DESC_LEN];   //  8 x N
    uint8_t         _service_name_length;                   //  8
    uint8_t         _service_name[MAX_DESC_LEN];            //  8 x N
} ServiceDescriptor;

// 6.2.15 Short event descriptor
typedef struct _ShortEventDescriptor
{
    uint8_t         _descriptor_tag;                        //  8
    uint8_t         _descriptor_length;                     //  8
    uint8_t         _ISO_639_language_code[3];              // 24
    uint8_t         _event_name_length;                     //  8
    uint8_t         _event_name[MAX_DESC_LEN];              //  8 x N
    uint8_t         _text_length;                           //  8
    uint8_t         _text[MAX_DESC_LEN];                    //  8 x N
} ShortEventDescriptor;

// 6.2.23 Digital copy control descriptor
typedef struct _DigitalCopyControlDescriptor
{
    uint8_t         _descriptor_tag;                        //  8
    uint8_t         _descriptor_length;                     //  8

} DigitalCopyControlDescriptor;

// 6.2.26 Audio compoenent descriptor
typedef struct _AudioComponentDescriptor
{
    uint8_t         _descriptor_tag;                        //  8
    uint8_t         _descriptor_length;                     //  8
    uint8_t         _reserved_future_use;                   //  4
    uint8_t         _stream_content;                        //  4
    uint8_t         _component_type;                        //  8
    uint8_t         _component_tag;                         //  8
    uint8_t         _stream_type;                           //  8
    uint8_t         _simulcast_group_tag;                   //  8
    uint8_t         _ES_multi_lingual_flag;                 //  1
    uint8_t         _main_component_flag;                   //  1
    uint8_t         _quality_indicator;                     //  2
    uint8_t         _sampling_rate;                         //  3
    uint8_t         _reserved_future_use_2;                 //  1
    uint8_t         _ISO_639_language_code[3];              // 24
    uint8_t         _ISO_639_language_code_2[3];            // 24 if (ES_multi_lingual_flag == 1)
    uint8_t         _text_char[MAX_DESC_LEN];               //  8 x N
} AudioComponentDescriptor;

// 6.2.33 Series descriptor
typedef struct _SeriesDescriptor
{
    uint8_t         _descriptor_tag;                        //  8
    uint8_t         _descriptor_length;                     //  8
    uint16_t        _series_id;                             // 16
    uint8_t         _repeat_label;                          //  4
    uint8_t         _program_pattern;                       //  3
    uint8_t         _expire_date_valid_flag;                //  1
    uint16_t        _expire_date;                           // 16
    uint16_t        _episode_number;                        // 12
    uint16_t        _last_episode_number;                   // 12
    uint8_t         _series_name[MAX_DESC_LEN];             //  8 x N
} SeriesDescriptor;


typedef struct _OtherDescriptor
{
    uint8_t         _descriptor_tag;                        //  8
    uint8_t         _descriptor_length;                     //  8
    uint8_t         _descriptor[MAX_DESC_LEN];              //  8 x N
} OtherDescriptor;

typedef union _Descriptor
{
    uint8_t                         _descriptor_tag;
    BouquetNameDescriptor           _bouquet_name;
    ComponentDescriptor             _component;
    ContentDescriptor               _content;
    ExtendedEventDescriptor         _extended_event;
    ServiceDescriptor               _service;
    ShortEventDescriptor            _short_event;
    DigitalCopyControlDescriptor    _digital_copy_control;
    AudioComponentDescriptor        _audio_component;
    SeriesDescriptor                _series;
    OtherDescriptor                 _other;
} Descriptor;

class Table
{
protected:
    uint16_t    _pid;
    uint16_t    _length;
    uint8_t     _section[MAX_SECT_LEN];

    virtual bool decode_section() = 0;

public:
    Table();
    virtual ~Table();
    bool decode(Header *header, uint8_t *packet);
    void reset();

    static uint16_t parseDescriptor(uint8_t *buf, uint16_t length, Descriptor *descriptor);


public:
    static int GetCrc32(unsigned char* data, int length);
};

} // TS
} // MPEG2
