// Copyright (c) 2012 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS.  All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#ifndef MKVPARSER_MKVPARSER_H_
#define MKVPARSER_MKVPARSER_H_

#include <cstddef>

namespace mkvparser {

const int E_PARSE_FAILED = -1;
const int E_FILE_FORMAT_INVALID = -2;
const int E_BUFFER_NOT_FULL = -3;

class IMkvReader {
 public:
  virtual int Read(long long pos, long len, unsigned char* buf) = 0;
  virtual int Length(long long* total, long long* available) = 0;

 protected:
  virtual ~IMkvReader() {}
};

template <typename Type>
Type* SafeArrayAlloc(unsigned long long num_elements,
                     unsigned long long element_size);
long long GetUIntLength(IMkvReader*, long long, long&);
long long ReadUInt(IMkvReader*, long long, long&);
long long ReadID(IMkvReader* pReader, long long pos, long& len);
long long UnserializeUInt(IMkvReader*, long long pos, long long size);

long UnserializeFloat(IMkvReader*, long long pos, long long size, double&);
long UnserializeInt(IMkvReader*, long long pos, long long size,
                    long long& result);

long UnserializeString(IMkvReader*, long long pos, long long size, char*& str);

long ParseElementHeader(IMkvReader* pReader,
                        long long& pos,  // consume id and size fields
                        long long stop,  // if you know size of element's parent
                        long long& id, long long& size);

bool Match(IMkvReader*, long long&, unsigned long, long long&);
bool Match(IMkvReader*, long long&, unsigned long, unsigned char*&, size_t&);

void GetVersion(int& major, int& minor, int& build, int& revision);

struct EBMLHeader {
  EBMLHeader();
  ~EBMLHeader();
  long long m_version;
  long long m_readVersion;
  long long m_maxIdLength;
  long long m_maxSizeLength;
  char* m_docType;
  long long m_docTypeVersion;
  long long m_docTypeReadVersion;

  long long Parse(IMkvReader*, long long&);
  void Init();
};

class Segment;
class Track;
class Cluster;

class Block {
  Block(const Block&);
  Block& operator=(const Block&);

 public:
  const long long m_start;
  const long long m_size;

  Block(long long start, long long size, long long discard_padding);
  ~Block();

  long Parse(const Cluster*);

  long long GetTrackNumber() const;
  long long GetTimeCode(const Cluster*) const;  // absolute, but not scaled
  long long GetTime(const Cluster*) const;  // absolute, and scaled (ns)
  bool IsKey() const;
  void SetKey(bool);
  bool IsInvisible() const;

  enum Lacing { kLacingNone, kLacingXiph, kLacingFixed, kLacingEbml };
  Lacing GetLacing() const;

  int GetFrameCount() const;  // to index frames: [0, count)

  struct Frame {
    long long pos;  // absolute offset
    long len;

    long Read(IMkvReader*, unsigned char*) const;
  };

  const Frame& GetFrame(int frame_index) const;

  long long GetDiscardPadding() const;

 private:
  long long m_track;  // Track::Number()
  short m_timecode;  // relative to cluster
  unsigned char m_flags;

  Frame* m_frames;
  int m_frame_count;

 protected:
  const long long m_discard_padding;
};

class BlockEntry {
  BlockEntry(const BlockEntry&);
  BlockEntry& operator=(const BlockEntry&);

 protected:
  BlockEntry(Cluster*, long index);

 public:
  virtual ~BlockEntry();

  bool EOS() const { return (GetKind() == kBlockEOS); }
  const Cluster* GetCluster() const;
  long GetIndex() const;
  virtual const Block* GetBlock() const = 0;

  enum Kind { kBlockEOS, kBlockSimple, kBlockGroup };
  virtual Kind GetKind() const = 0;

 protected:
  Cluster* const m_pCluster;
  const long m_index;
};

class SimpleBlock : public BlockEntry {
  SimpleBlock(const SimpleBlock&);
  SimpleBlock& operator=(const SimpleBlock&);

 public:
  SimpleBlock(Cluster*, long index, long long start, long long size);
  long Parse();

  Kind GetKind() const;
  const Block* GetBlock() const;

 protected:
  Block m_block;
};

class BlockGroup : public BlockEntry {
  BlockGroup(const BlockGroup&);
  BlockGroup& operator=(const BlockGroup&);

 public:
  BlockGroup(Cluster*, long index,
             long long block_start,  // absolute pos of block's payload
             long long block_size,  // size of block's payload
             long long prev, long long next, long long duration,
             long long discard_padding);

  long Parse();

  Kind GetKind() const;
  const Block* GetBlock() const;

  long long GetPrevTimeCode() const;  // relative to block's time
  long long GetNextTimeCode() const;  // as above
  long long GetDurationTimeCode() const;

 private:
  Block m_block;
  const long long m_prev;
  const long long m_next;
  const long long m_duration;
};

///////////////////////////////////////////////////////////////
// ContentEncoding element
// Elements used to describe if the track data has been encrypted or
// compressed with zlib or header stripping.
class ContentEncoding {
 public:
  enum { kCTR = 1 };

  ContentEncoding();
  ~ContentEncoding();

  // ContentCompression element names
  struct ContentCompression {
    ContentCompression();
    ~ContentCompression();

    unsigned long long algo;
    unsigned char* settings;
    long long settings_len;
  };

  // ContentEncAESSettings element names
  struct ContentEncAESSettings {
    ContentEncAESSettings() : cipher_mode(kCTR) {}
    ~ContentEncAESSettings() {}

    unsigned long long cipher_mode;
  };

  // ContentEncryption element names
  struct ContentEncryption {
    ContentEncryption();
    ~ContentEncryption();

    unsigned long long algo;
    unsigned char* key_id;
    long long key_id_len;
    unsigned char* signature;
    long long signature_len;
    unsigned char* sig_key_id;
    long long sig_key_id_len;
    unsigned long long sig_algo;
    unsigned long long sig_hash_algo;

    ContentEncAESSettings aes_settings;
  };

  // Returns ContentCompression represented by |idx|. Returns NULL if |idx|
  // is out of bounds.
  const ContentCompression* GetCompressionByIndex(unsigned long idx) const;

  // Returns number of ContentCompression elements in this ContentEncoding
  // element.
  unsigned long GetCompressionCount() const;

  // Parses the ContentCompression element from |pReader|. |start| is the
  // starting offset of the ContentCompression payload. |size| is the size in
  // bytes of the ContentCompression payload. |compression| is where the parsed
  // values will be stored.
  long ParseCompressionEntry(long long start, long long size,
                             IMkvReader* pReader,
                             ContentCompression* compression);

  // Returns ContentEncryption represented by |idx|. Returns NULL if |idx|
  // is out of bounds.
  const ContentEncryption* GetEncryptionByIndex(unsigned long idx) const;

  // Returns number of ContentEncryption elements in this ContentEncoding
  // element.
  unsigned long GetEncryptionCount() const;

  // Parses the ContentEncAESSettings element from |pReader|. |start| is the
  // starting offset of the ContentEncAESSettings payload. |size| is the
  // size in bytes of the ContentEncAESSettings payload. |encryption| is
  // where the parsed values will be stored.
  long ParseContentEncAESSettingsEntry(long long start, long long size,
                                       IMkvReader* pReader,
                                       ContentEncAESSettings* aes);

  // Parses the ContentEncoding element from |pReader|. |start| is the
  // starting offset of the ContentEncoding payload. |size| is the size in
  // bytes of the ContentEncoding payload. Returns true on success.
  long ParseContentEncodingEntry(long long start, long long size,
                                 IMkvReader* pReader);

  // Parses the ContentEncryption element from |pReader|. |start| is the
  // starting offset of the ContentEncryption payload. |size| is the size in
  // bytes of the ContentEncryption payload. |encryption| is where the parsed
  // values will be stored.
  long ParseEncryptionEntry(long long start, long long size,
                            IMkvReader* pReader, ContentEncryption* encryption);

  unsigned long long encoding_order() const { return encoding_order_; }
  unsigned long long encoding_scope() const { return encoding_scope_; }
  unsigned long long encoding_type() const { return encoding_type_; }

 private:
  // Member variables for list of ContentCompression elements.
  ContentCompression** compression_entries_;
  ContentCompression** compression_entries_end_;

  // Member variables for list of ContentEncryption elements.
  ContentEncryption** encryption_entries_;
  ContentEncryption** encryption_entries_end_;

  // ContentEncoding element names
  unsigned long long encoding_order_;
  unsigned long long encoding_scope_;
  unsigned long long encoding_type_;

  // LIBWEBM_DISALLOW_COPY_AND_ASSIGN(ContentEncoding);
  ContentEncoding(const ContentEncoding&);
  ContentEncoding& operator=(const ContentEncoding&);
};

class Track {
  Track(const Track&);
  Track& operator=(const Track&);

 public:
  class Info;
  static long Create(Segment*, const Info&, long long element_start,
                     long long element_size, Track*&);

  enum Type { kVideo = 1, kAudio = 2, kSubtitle = 0x11, kMetadata = 0x21 };

  Segment* const m_pSegment;
  const long long m_element_start;
  const long long m_element_size;
  virtual ~Track();

  long GetType() const;
  long GetNumber() const;
  unsigned long long GetUid() const;
  const char* GetNameAsUTF8() const;
  const char* GetLanguage() const;
  const char* GetCodecNameAsUTF8() const;
  const char* GetCodecId() const;
  const unsigned char* GetCodecPrivate(size_t&) const;
  bool GetLacing() const;
  unsigned long long GetDefaultDuration() const;
  unsigned long long GetCodecDelay() const;
  unsigned long long GetSeekPreRoll() const;

  const BlockEntry* GetEOS() const;

  struct Settings {
    long long start;
    long long size;
  };

  class Info {
   public:
    Info();
    ~Info();
    int Copy(Info&) const;
    void Clear();
    long type;
    long number;
    unsigned long long uid;
    unsigned long long defaultDuration;
    unsigned long long codecDelay;
    unsigned long long seekPreRoll;
    char* nameAsUTF8;
    char* language;
    char* codecId;
    char* codecNameAsUTF8;
    unsigned char* codecPrivate;
    size_t codecPrivateSize;
    bool lacing;
    Settings settings;

   private:
    Info(const Info&);
    Info& operator=(const Info&);
    int CopyStr(char* Info::*str, Info&) const;
  };

  long GetFirst(const BlockEntry*&) const;
  long GetNext(const BlockEntry* pCurr, const BlockEntry*& pNext) const;
  virtual bool VetEntry(const BlockEntry*) const;
  virtual long Seek(long long time_ns, const BlockEntry*&) const;

  const ContentEncoding* GetContentEncodingByIndex(unsigned long idx) const;
  unsigned long GetContentEncodingCount() const;

  long ParseContentEncodingsEntry(long long start, long long size);

 protected:
  Track(Segment*, long long element_start, long long element_size);

  Info m_info;

  class EOSBlock : public BlockEntry {
   public:
    EOSBlock();

    Kind GetKind() const;
    const Block* GetBlock() const;
  };

  EOSBlock m_eos;

 private:
  ContentEncoding** content_encoding_entries_;
  ContentEncoding** content_encoding_entries_end_;
};

struct PrimaryChromaticity {
  PrimaryChromaticity() : x(0), y(0) {}
  ~PrimaryChromaticity() {}
  static bool Parse(IMkvReader* reader, long long read_pos,
                    long long value_size, bool is_x,
                    PrimaryChromaticity** chromaticity);
  float x;
  float y;
};

struct MasteringMetadata {
  static const float kValueNotPresent;

  MasteringMetadata()
      : r(NULL),
        g(NULL),
        b(NULL),
        white_point(NULL),
        luminance_max(kValueNotPresent),
        luminance_min(kValueNotPresent) {}
  ~MasteringMetadata() {
    delete r;
    delete g;
    delete b;
    delete white_point;
  }

  static bool Parse(IMkvReader* reader, long long element_start,
                    long long element_size,
                    MasteringMetadata** mastering_metadata);

  PrimaryChromaticity* r;
  PrimaryChromaticity* g;
  PrimaryChromaticity* b;
  PrimaryChromaticity* white_point;
  float luminance_max;
  float luminance_min;
};

struct Colour {
  static const long long kValueNotPresent;

  // Unless otherwise noted all values assigned upon construction are the
  // equivalent of unspecified/default.
  Colour()
      : matrix_coefficients(kValueNotPresent),
        bits_per_channel(kValueNotPresent),
        chroma_subsampling_horz(kValueNotPresent),
        chroma_subsampling_vert(kValueNotPresent),
        cb_subsampling_horz(kValueNotPresent),
        cb_subsampling_vert(kValueNotPresent),
        chroma_siting_horz(kValueNotPresent),
        chroma_siting_vert(kValueNotPresent),
        range(kValueNotPresent),
        transfer_characteristics(kValueNotPresent),
        primaries(kValueNotPresent),
        max_cll(kValueNotPresent),
        max_fall(kValueNotPresent),
        mastering_metadata(NULL) {}
  ~Colour() {
    delete mastering_metadata;
    mastering_metadata = NULL;
  }

  static bool Parse(IMkvReader* reader, long long element_start,
                    long long element_size, Colour** colour);

  long long matrix_coefficients;
  long long bits_per_channel;
  long long chroma_subsampling_horz;
  long long chroma_subsampling_vert;
  long long cb_subsampling_horz;
  long long cb_subsampling_vert;
  long long chroma_siting_horz;
  long long chroma_siting_vert;
  long long range;
  long long transfer_characteristics;
  long long primaries;
  long long max_cll;
  long long max_fall;

  MasteringMetadata* mastering_metadata;
};

struct Projection {
  enum ProjectionType {
    kTypeNotPresent = -1,
    kRectangular = 0,
    kEquirectangular = 1,
    kCubeMap = 2,
    kMesh = 3,
  };
  static const float kValueNotPresent;
  Projection()
      : type(kTypeNotPresent),
        private_data(NULL),
        private_data_length(0),
        pose_yaw(kValueNotPresent),
        pose_pitch(kValueNotPresent),
        pose_roll(kValueNotPresent) {}
  ~Projection() { delete[] private_data; }
  static bool Parse(IMkvReader* reader, long long element_start,
                    long long element_size, Projection** projection);

  ProjectionType type;
  unsigned char* private_data;
  size_t private_data_length;
  float pose_yaw;
  float pose_pitch;
  float pose_roll;
};

class VideoTrack : public Track {
  VideoTrack(const VideoTrack&);
  VideoTrack& operator=(const VideoTrack&);

  VideoTrack(Segment*, long long element_start, long long element_size);

 public:
  virtual ~VideoTrack();
  static long Parse(Segment*, const Info&, long long element_start,
                    long long element_size, VideoTrack*&);

  long long GetWidth() const;
  long long GetHeight() const;
  long long GetDisplayWidth() const;
  long long GetDisplayHeight() const;
  long long GetDisplayUnit() const;
  long long GetStereoMode() const;
  double GetFrameRate() const;

  bool VetEntry(const BlockEntry*) const;
  long Seek(long long time_ns, const BlockEntry*&) const;

  Colour* GetColour() const;

  Projection* GetProjection() const;

 private:
  long long m_width;
  long long m_height;
  long long m_display_width;
  long long m_display_height;
  long long m_display_unit;
  long long m_stereo_mode;

  double m_rate;

  Colour* m_colour;
  Projection* m_projection;
};

class AudioTrack : public Track {
  AudioTrack(const AudioTrack&);
  AudioTrack& operator=(const AudioTrack&);

  AudioTrack(Segment*, long long element_start, long long element_size);

 public:
  static long Parse(Segment*, const Info&, long long element_start,
                    long long element_size, AudioTrack*&);

  double GetSamplingRate() const;
  long long GetChannels() const;
  long long GetBitDepth() const;

 private:
  double m_rate;
  long long m_channels;
  long long m_bitDepth;
};

class Tracks {
  Tracks(const Tracks&);
  Tracks& operator=(const Tracks&);

 public:
  Segment* const m_pSegment;
  const long long m_start;
  const long long m_size;
  const long long m_element_start;
  const long long m_element_size;

  Tracks(Segment*, long long start, long long size, long long element_start,
         long long element_size);

  ~Tracks();

  long Parse();

  unsigned long GetTracksCount() const;

  const Track* GetTrackByNumber(long tn) const;
  const Track* GetTrackByIndex(unsigned long idx) const;

 private:
  Track** m_trackEntries;
  Track** m_trackEntriesEnd;

  long ParseTrackEntry(long long payload_start, long long payload_size,
                       long long element_start, long long element_size,
                       Track*&) const;
};

class Chapters {
  Chapters(const Chapters&);
  Chapters& operator=(const Chapters&);

 public:
  Segment* const m_pSegment;
  const long long m_start;
  const long long m_size;
  const long long m_element_start;
  const long long m_element_size;

  Chapters(Segment*, long long payload_start, long long payload_size,
           long long element_start, long long element_size);

  ~Chapters();

  long Parse();

  class Atom;
  class Edition;

  class Display {
    friend class Atom;
    Display();
    Display(const Display&);
    ~Display();
    Display& operator=(const Display&);

   public:
    const char* GetString() const;
    const char* GetLanguage() const;
    const char* GetCountry() const;

   private:
    void Init();
    void ShallowCopy(Display&) const;
    void Clear();
    long Parse(IMkvReader*, long long pos, long long size);

    char* m_string;
    char* m_language;
    char* m_country;
  };

  class Atom {
    friend class Edition;
    Atom();
    Atom(const Atom&);
    ~Atom();
    Atom& operator=(const Atom&);

   public:
    unsigned long long GetUID() const;
    const char* GetStringUID() const;

    long long GetStartTimecode() const;
    long long GetStopTimecode() const;

    long long GetStartTime(const Chapters*) const;
    long long GetStopTime(const Chapters*) const;

    int GetDisplayCount() const;
    const Display* GetDisplay(int index) const;

   private:
    void Init();
    void ShallowCopy(Atom&) const;
    void Clear();
    long Parse(IMkvReader*, long long pos, long long size);
    static long long GetTime(const Chapters*, long long timecode);

    long ParseDisplay(IMkvReader*, long long pos, long long size);
    bool ExpandDisplaysArray();

    char* m_string_uid;
    unsigned long long m_uid;
    long long m_start_timecode;
    long long m_stop_timecode;

    Display* m_displays;
    int m_displays_size;
    int m_displays_count;
  };

  class Edition {
    friend class Chapters;
    Edition();
    Edition(const Edition&);
    ~Edition();
    Edition& operator=(const Edition&);

   public:
    int GetAtomCount() const;
    const Atom* GetAtom(int index) const;

   private:
    void Init();
    void ShallowCopy(Edition&) const;
    void Clear();
    long Parse(IMkvReader*, long long pos, long long size);

    long ParseAtom(IMkvReader*, long long pos, long long size);
    bool ExpandAtomsArray();

    Atom* m_atoms;
    int m_atoms_size;
    int m_atoms_count;
  };

  int GetEditionCount() const;
  const Edition* GetEdition(int index) const;

 private:
  long ParseEdition(long long pos, long long size);
  bool ExpandEditionsArray();

  Edition* m_editions;
  int m_editions_size;
  int m_editions_count;
};

class Tags {
  Tags(const Tags&);
  Tags& operator=(const Tags&);

 public:
  Segment* const m_pSegment;
  const long long m_start;
  const long long m_size;
  const long long m_element_start;
  const long long m_element_size;

  Tags(Segment*, long long payload_start, long long payload_size,
       long long element_start, long long element_size);

  ~Tags();

  long Parse();

  class Tag;
  class SimpleTag;

  class SimpleTag {
    friend class Tag;
    SimpleTag();
    SimpleTag(const SimpleTag&);
    ~SimpleTag();
    SimpleTag& operator=(const SimpleTag&);

   public:
    const char* GetTagName() const;
    const char* GetTagString() const;

   private:
    void Init();
    void ShallowCopy(SimpleTag&) const;
    void Clear();
    long Parse(IMkvReader*, long long pos, long long size);

    char* m_tag_name;
    char* m_tag_string;
  };

  class Tag {
    friend class Tags;
    Tag();
    Tag(const Tag&);
    ~Tag();
    Tag& operator=(const Tag&);

   public:
    int GetSimpleTagCount() const;
    const SimpleTag* GetSimpleTag(int index) const;

   private:
    void Init();
    void ShallowCopy(Tag&) const;
    void Clear();
    long Parse(IMkvReader*, long long pos, long long size);

    long ParseSimpleTag(IMkvReader*, long long pos, long long size);
    bool ExpandSimpleTagsArray();

    SimpleTag* m_simple_tags;
    int m_simple_tags_size;
    int m_simple_tags_count;
  };

  int GetTagCount() const;
  const Tag* GetTag(int index) const;

 private:
  long ParseTag(long long pos, long long size);
  bool ExpandTagsArray();

  Tag* m_tags;
  int m_tags_size;
  int m_tags_count;
};

class SegmentInfo {
  SegmentInfo(const SegmentInfo&);
  SegmentInfo& operator=(const SegmentInfo&);

 public:
  Segment* const m_pSegment;
  const long long m_start;
  const long long m_size;
  const long long m_element_start;
  const long long m_element_size;

  SegmentInfo(Segment*, long long start, long long size,
              long long element_start, long long element_size);

  ~SegmentInfo();

  long Parse();

  long long GetTimeCodeScale() const;
  long long GetDuration() const;  // scaled
  const char* GetMuxingAppAsUTF8() const;
  const char* GetWritingAppAsUTF8() const;
  const char* GetTitleAsUTF8() const;

 private:
  long long m_timecodeScale;
  double m_duration;
  char* m_pMuxingAppAsUTF8;
  char* m_pWritingAppAsUTF8;
  char* m_pTitleAsUTF8;
};

class SeekHead {
  SeekHead(const SeekHead&);
  SeekHead& operator=(const SeekHead&);

 public:
  Segment* const m_pSegment;
  const long long m_start;
  const long long m_size;
  const long long m_element_start;
  const long long m_element_size;

  SeekHead(Segment*, long long start, long long size, long long element_start,
           long long element_size);

  ~SeekHead();

  long Parse();

  struct Entry {
    Entry();

    // the SeekHead entry payload
    long long id;
    long long pos;

    // absolute pos of SeekEntry ID
    long long element_start;

    // SeekEntry ID size + size size + payload
    long long element_size;
  };

  int GetCount() const;
  const Entry* GetEntry(int idx) const;

  struct VoidElement {
    // absolute pos of Void ID
    long long element_start;

    // ID size + size size + payload size
    long long element_size;
  };

  int GetVoidElementCount() const;
  const VoidElement* GetVoidElement(int idx) const;

 private:
  Entry* m_entries;
  int m_entry_count;

  VoidElement* m_void_elements;
  int m_void_element_count;

  static bool ParseEntry(IMkvReader*,
                         long long pos,  // payload
                         long long size, Entry*);
};

class Cues;
class CuePoint {
  friend class Cues;

  CuePoint(long, long long);
  ~CuePoint();

  CuePoint(const CuePoint&);
  CuePoint& operator=(const CuePoint&);

 public:
  long long m_element_start;
  long long m_element_size;

  bool Load(IMkvReader*);

  long long GetTimeCode() const;  // absolute but unscaled
  long long GetTime(const Segment*) const;  // absolute and scaled (ns units)

  struct TrackPosition {
    long long m_track;
    long long m_pos;  // of cluster
    long long m_block;
    // codec_state  //defaults to 0
    // reference = clusters containing req'd referenced blocks
    //  reftime = timecode of the referenced block

    bool Parse(IMkvReader*, long long, long long);
  };

  const TrackPosition* Find(const Track*) const;

 private:
  const long m_index;
  long long m_timecode;
  TrackPosition* m_track_positions;
  size_t m_track_positions_count;
};

class Cues {
  friend class Segment;

  Cues(Segment*, long long start, long long size, long long element_start,
       long long element_size);
  ~Cues();

  Cues(const Cues&);
  Cues& operator=(const Cues&);

 public:
  Segment* const m_pSegment;
  const long long m_start;
  const long long m_size;
  const long long m_element_start;
  const long long m_element_size;

  bool Find(  // lower bound of time_ns
      long long time_ns, const Track*, const CuePoint*&,
      const CuePoint::TrackPosition*&) const;

  const CuePoint* GetFirst() const;
  const CuePoint* GetLast() const;
  const CuePoint* GetNext(const CuePoint*) const;

  const BlockEntry* GetBlock(const CuePoint*,
                             const CuePoint::TrackPosition*) const;

  bool LoadCuePoint() const;
  long GetCount() const;  // loaded only
  // long GetTotal() const;  //loaded + preloaded
  bool DoneParsing() const;

 private:
  bool Init() const;
  bool PreloadCuePoint(long&, long long) const;

  mutable CuePoint** m_cue_points;
  mutable long m_count;
  mutable long m_preload_count;
  mutable long long m_pos;
};

class Cluster {
  friend class Segment;

  Cluster(const Cluster&);
  Cluster& operator=(const Cluster&);

 public:
  Segment* const m_pSegment;

 public:
  static Cluster* Create(Segment*,
                         long index,  // index in segment
                         long long off);  // offset relative to segment
  // long long element_size);

  Cluster();  // EndOfStream
  ~Cluster();

  bool EOS() const;

  long long GetTimeCode() const;  // absolute, but not scaled
  long long GetTime() const;  // absolute, and scaled (nanosecond units)
  long long GetFirstTime() const;  // time (ns) of first (earliest) block
  long long GetLastTime() const;  // time (ns) of last (latest) block

  long GetFirst(const BlockEntry*&) const;
  long GetLast(const BlockEntry*&) const;
  long GetNext(const BlockEntry* curr, const BlockEntry*& next) const;

  const BlockEntry* GetEntry(const Track*, long long ns = -1) const;
  const BlockEntry* GetEntry(const CuePoint&,
                             const CuePoint::TrackPosition&) const;
  // const BlockEntry* GetMaxKey(const VideoTrack*) const;

  //    static bool HasBlockEntries(const Segment*, long long);

  static long HasBlockEntries(const Segment*, long long idoff, long long& pos,
                              long& size);

  long GetEntryCount() const;

  long Load(long long& pos, long& size) const;

  long Parse(long long& pos, long& size) const;
  long GetEntry(long index, const mkvparser::BlockEntry*&) const;

 protected:
  Cluster(Segment*, long index, long long element_start);
  // long long element_size);

 public:
  const long long m_element_start;
  long long GetPosition() const;  // offset relative to segment

  long GetIndex() const;
  long long GetElementSize() const;
  // long long GetPayloadSize() const;

  // long long Unparsed() const;

 private:
  long m_index;
  mutable long long m_pos;
  // mutable long long m_size;
  mutable long long m_element_size;
  mutable long long m_timecode;
  mutable BlockEntry** m_entries;
  mutable long m_entries_size;
  mutable long m_entries_count;

  long ParseSimpleBlock(long long, long long&, long&);
  long ParseBlockGroup(long long, long long&, long&);

  long CreateBlock(long long id, long long pos, long long size,
                   long long discard_padding);
  long CreateBlockGroup(long long start_offset, long long size,
                        long long discard_padding);
  long CreateSimpleBlock(long long, long long);
};

class Segment {
  friend class Cues;
  friend class Track;
  friend class VideoTrack;

  Segment(const Segment&);
  Segment& operator=(const Segment&);

 private:
  Segment(IMkvReader*, long long elem_start,
          // long long elem_size,
          long long pos, long long size);

 public:
  IMkvReader* const m_pReader;
  const long long m_element_start;
  // const long long m_element_size;
  const long long m_start;  // posn of segment payload
  const long long m_size;  // size of segment payload
  Cluster m_eos;  // TODO: make private?

  static long long CreateInstance(IMkvReader*, long long, Segment*&);
  ~Segment();

  long Load();  // loads headers and all clusters

  // for incremental loading
  // long long Unparsed() const;
  bool DoneParsing() const;
  long long ParseHeaders();  // stops when first cluster is found
  // long FindNextCluster(long long& pos, long& size) const;
  long LoadCluster(long long& pos, long& size);  // load one cluster
  long LoadCluster();

  long ParseNext(const Cluster* pCurr, const Cluster*& pNext, long long& pos,
                 long& size);

  const SeekHead* GetSeekHead() const;
  const Tracks* GetTracks() const;
  const SegmentInfo* GetInfo() const;
  const Cues* GetCues() const;
  const Chapters* GetChapters() const;
  const Tags* GetTags() const;

  long long GetDuration() const;

  unsigned long GetCount() const;
  const Cluster* GetFirst() const;
  const Cluster* GetLast() const;
  const Cluster* GetNext(const Cluster*);

  const Cluster* FindCluster(long long time_nanoseconds) const;
  // const BlockEntry* Seek(long long time_nanoseconds, const Track*) const;

  const Cluster* FindOrPreloadCluster(long long pos);

  long ParseCues(long long cues_off,  // offset relative to start of segment
                 long long& parse_pos, long& parse_len);

 private:
  long long m_pos;  // absolute file posn; what has been consumed so far
  Cluster* m_pUnknownSize;

  SeekHead* m_pSeekHead;
  SegmentInfo* m_pInfo;
  Tracks* m_pTracks;
  Cues* m_pCues;
  Chapters* m_pChapters;
  Tags* m_pTags;
  Cluster** m_clusters;
  long m_clusterCount;  // number of entries for which m_index >= 0
  long m_clusterPreloadCount;  // number of entries for which m_index < 0
  long m_clusterSize;  // array size

  long DoLoadCluster(long long&, long&);
  long DoLoadClusterUnknownSize(long long&, long&);
  long DoParseNext(const Cluster*&, long long&, long&);

  bool AppendCluster(Cluster*);
  bool PreloadCluster(Cluster*, ptrdiff_t);

  // void ParseSeekHead(long long pos, long long size);
  // void ParseSeekEntry(long long pos, long long size);
  // void ParseCues(long long);

  const BlockEntry* GetBlock(const CuePoint&, const CuePoint::TrackPosition&);
};

}  // namespace mkvparser

inline long mkvparser::Segment::LoadCluster() {
  long long pos;
  long size;

  return LoadCluster(pos, size);
}

#endif  // MKVPARSER_MKVPARSER_H_
