#ifndef dvd_packets_h
#define dvd_packets_h

#include "dvd_commons.h"
#include "ka_error.h"

// Program Control Information (PCI) packet

typedef struct dvd_pci_s dvd_pci_t;

typedef struct
{
  uint8_t color_emphasis2;
  uint8_t color_emphasis1;
  uint8_t color_pattern;
  uint8_t color_background;
  uint8_t alpha_emphasis2;
  uint8_t alpha_emphasis1;
  uint8_t alpha_pattern;
  uint8_t alpha_background;
} dvd_pci_colors;


struct dvd_pci_s
{
  // work data
  dvd_pci_t* next;
  int active;

  // real data
  struct
  {
    uint32_t   cur_lbn;     // logical block number (lbn, sector) of the PCI
    uint32_t   category;    // flags
    uint32_t   userops_ctl; // prohibited userops mask
    uint32_t   start_pts;   // vobu start pts (90Khz)
    uint32_t   end_pts;     // vobu end pts
    uint32_t   seq_end_pts; // vobu end pts if sequence end code
    dvd_time_t cell_time;   // cell elapsed time
    char       iscr[32];    // International Standard Recording Code
  } vobu;
  uint32_t  angle_rel_lbn[9]; // relative lbn to angle x
                              // top bit: 0 forward, 1 backward
                              // 00 00 00 00 no such angle
                              // 7f ff ff ff no more data for this angle
  struct
  {
    uint16_t  status; // 00 no highlight, 01 new highlight
                      // 10 from previous VOBU, 11 from prev except commands
    uint32_t  start_pts;
    uint32_t  end_pts;
    uint32_t  button_selection_end_pts; // ignore user after this
    struct
    {
      uint8_t nr_groups; // 1, 2 or 3 with 36/18/12 buttons
      uint8_t type[3]; // 0 4/3,  1 wide, 2 letterbox, 4 pan&scan
    } groups;
    uint8_t offset_button; // for menus extending over multiple screens
    uint8_t nr_buttons;
    uint8_t nr_of_selectable_buttons; // by numeric input
    uint8_t force_select_button; // if > 0, button to highlight at start_pts
    uint8_t force_action_button; // if > 0, button to activate at end_pts
    dvd_pci_colors selection[3];
    dvd_pci_colors action[3];
  } highlight;
  struct
  {
    uint8_t color_table; // 0 = none
    uint8_t auto_action; // 1 = yes
    int  x_start;
    int  x_end;
    int  y_start;
    int  y_end;
    struct
    {
      uint8_t  up;
      uint8_t  down;
      uint8_t  left;
      uint8_t  right;
    } new_button;
    dvd_cmd_t cmd;
  } buttons[36];
};

// Data Stream Information (DSI) packet

typedef struct
{
  uint32_t   scr;
  uint32_t   cur_lbn;           // logical block number (lbn, sector) of the DSI
  uint32_t   vobu_last;         // offset in sectors to last sector of VOBU
  uint32_t   refframes_last[3]; // offset to last sector of reference frames
  uint16_t   vob_nr;
  uint8_t    cell_nr;  // within vob
  dvd_time_t cell_time;
  uint16_t   flags;
  uint32_t   ilvu_last; // offset to last sector of cur angle in ILVU, 0 if no angles
  uint32_t   ilvu_next; // offset to first sector of cur angle in next ILVU
                        // 0 if no angles, 0xffffffff if no more angles ILVU
  uint16_t   ilvu_next_size;
  uint32_t   vob_first_pts; // pts of first frame in VOB (yes VOB)
  uint32_t   vob_last_pts;  // pts of last frame in VOB
  uint32_t   audio_gap_pts[8][2]; // pts of gap x of audio stream y
  uint32_t   audio_gap_duration[8][2]; // duration of gaps
  struct
  {
    uint32_t next_ilvu; // offset to first sector of angle x in next ILVU
    uint16_t ilvu_size; // size in sector of angle in next ivlu
  } angles[9];
  uint32_t   vobu_next_video; // offset to next vobu with video
                              // bit 31 direction, 0x(f|7)fffffff if none
  uint32_t   vobu_fsearch[19]; // offsets to next vobus in forward search
                               // bit 31 has video
                               // bit 30 intermediate vobus
                               // 0x3fffffff if no vobu
  uint32_t   vobu_next; // offset to next vobu in cur angle
                        // bit 31 has video
                        // 0x3fffffff if no vobu
  uint32_t   vobu_prev; // offset to prev vobu in cur angle
                        // bit 31 has video
                        // 0x3fffffff if no vobu
  uint32_t   vobu_bsearch[19]; // offsets to prev vobus in backward search
                               // bit 31 has video
                               // bit 30 intermediate vobus
                               // 0x3fffffff if no vobu
  uint32_t   vobu_prev_video; // offset to prev vobu with video
                              // bit 31 direction, 0x(f|7)fffffff if none
  uint16_t   offset_audio[8]; // offset in bytes to first audio stream x packet
  uint32_t   spu_vobu[32];    // offset to vobu with packets for spu x
                              // bit 31 direction, 0x00000000 if no spu x
                              // 0x7fffffff if in current vobu
} dvd_dsi_t;

int dvd_read_pci(ka_error_t* pErrorBlock, dvd_pci_t** ppci, const uint8_t* p);
int dvd_read_dsi(ka_error_t* pErrorBlock, dvd_dsi_t** pdsi, const uint8_t* p);

#endif
