#include "mp4.h"
#include "mp4_ms.h"

namespace MP4 {

  struct UUID_SampleEncryption_Sample_Entry {
    uint32_t BytesClear;
    uint32_t BytesEncrypted;
  };

  struct UUID_SampleEncryption_Sample {
    std::string InitializationVector;
    uint32_t NumberOfEntries;
    std::vector<UUID_SampleEncryption_Sample_Entry> Entries;
  };

  class PSSH: public fullBox {
    public:
      PSSH();
      std::string getSystemIDHex();
      void setSystemIDHex(const std::string & systemID);
      std::string toPrettyString(uint32_t indent = 0);
      size_t getKIDCount();
      size_t getDataSize();
      char * getData();
      void setData(const std::string & data);
  };

  class TENC: public fullBox {
    public:
      TENC();
      std::string toPrettyString(uint32_t indent = 0);
      size_t getDefaultIsEncrypted();
      void setDefaultIsEncrypted(size_t isEncrypted);
      size_t getDefaultIVSize();
      void setDefaultIVSize(uint8_t ivSize);
      std::string getDefaultKID();
      void setDefaultKID(const std::string & kid);
  };

  class SENC: public fullBox {
    public:
      SENC();
      uint32_t getSampleCount() const;
      void setSample(UUID_SampleEncryption_Sample newSample, size_t index);
      UUID_SampleEncryption_Sample getSample(size_t index) const;
      std::string toPrettyString(uint32_t indent = 0) const;
  };

  class SAIZ : public fullBox {
    public:
      SAIZ(size_t entryCount = 0);
      size_t getDefaultSampleSize();
      size_t getEntryCount();
      size_t getEntrySize(size_t entryNo);
      std::string toPrettyString(uint32_t indent = 0);
  };

  class SAIO : public fullBox {
    public:
      SAIO(size_t offset = 0);
      size_t getEntryCount();
      size_t getEntrySize(size_t entryNo);
      std::string toPrettyString(uint32_t indent = 0);
  };

  class UUID_SampleEncryption: public UUID {
    public:
      UUID_SampleEncryption();
      UUID_SampleEncryption(const SENC & senc);
      void setVersion(uint32_t newVersion);
      uint32_t getVersion();
      void setFlags(uint32_t newFlags);
      uint32_t getFlags();
      void setAlgorithmID(uint32_t newAlgorithmID);
      uint32_t getAlgorithmID();
      void setIVSize(uint32_t newIVSize);
      uint32_t getIVSize();
      void setKID(std::string newKID);
      std::string getKID();
      uint32_t getSampleCount();
      void setSample(UUID_SampleEncryption_Sample newSample, size_t index);
      UUID_SampleEncryption_Sample getSample(size_t index);
      std::string toPrettyString(uint32_t indent = 0);
  };

  class UUID_TrackEncryption: public UUID {
    public:
      UUID_TrackEncryption();
      void setVersion(uint32_t newVersion);
      uint32_t getVersion();
      void setFlags(uint32_t newFlags);
      uint32_t getFlags();
      void setDefaultAlgorithmID(uint32_t newAlgorithmID);
      uint32_t getDefaultAlgorithmID();
      void setDefaultIVSize(uint8_t newIVSize);
      uint8_t getDefaultIVSize();
      void setDefaultKID(std::string newKID);
      std::string getDefaultKID();
      std::string toPrettyString(uint32_t indent = 0);
  };

  class UUID_ProtectionSystemSpecificHeader: public UUID {
    public:
      UUID_ProtectionSystemSpecificHeader();
      void setVersion(uint32_t newVersion);
      uint32_t getVersion();
      void setFlags(uint32_t newFlags);
      uint32_t getFlags();
      void setSystemID(std::string newID);
      std::string getSystemID();
      void setDataSize(uint32_t newDataSize);
      uint32_t getDataSize();
      void setData(std::string newData);
      std::string getData();
      std::string toPrettyString(uint32_t indent = 0);
  };

  class SINF: public Box {
    public:
      SINF();
      void setEntry(Box & newEntry, uint32_t no);
      Box & getEntry(uint32_t no);
      std::string toPrettyString(uint32_t indent = 0);
  };

  class FRMA: public Box {
    public:
      FRMA(const std::string & originalFormat = "");
      void setOriginalFormat(const std::string & newFormat);
      std::string getOriginalFormat();
      std::string toPrettyString(uint32_t indent = 0);
  };

  class SCHM: public fullBox {
    public:
      SCHM(uint32_t schemeType = 0x636E6563, uint32_t schemeVersion = 0x00000100);//CENC defaults
      void setSchemeType(uint32_t newType);
      uint32_t getSchemeType();
      void setSchemeVersion(uint32_t newVersion);
      uint32_t getSchemeVersion();
      void setSchemeURI(std::string newURI);
      std::string getSchemeURI();
      std::string toPrettyString(uint32_t indent = 0);
  };

  class SCHI: public Box {
    public:
      SCHI();
      void setContent(Box & newContent);
      Box & getContent();
      std::string toPrettyString(uint32_t indent = 0);
  };

}