// https://github.com/gpac/mp4box.js/issues/233

import { Flags } from "./utils/tauri";

declare module "mp4box";
export interface MP4MediaTrack {
  id: number;
  created: Date;
  modified: Date;
  movie_duration: number;
  layer: number;
  alternate_group: number;
  volume: number;
  track_width: number;
  track_height: number;
  timescale: number;
  duration: number;
  bitrate: number;
  codec: string;
  language: string;
  nb_samples: number;
}

export interface MP4VideoData {
  width: number;
  height: number;
}

export interface MP4VideoTrack extends MP4MediaTrack {
  video: MP4VideoData;
}

export interface MP4AudioData {
  sample_rate: number;
  channel_count: number;
  sample_size: number;
}

export interface MP4AudioTrack extends MP4MediaTrack {
  audio: MP4AudioData;
}

export type MP4Track = MP4VideoTrack | MP4AudioTrack;

export interface MP4Info {
  duration: number;
  timescale: number;
  fragment_duration: number;
  isFragmented: boolean;
  isProgressive: boolean;
  hasIOD: boolean;
  brands: string[];
  created: Date;
  modified: Date;
  tracks: MP4Track[];
  mime: string;
  audioTracks: MP4AudioTrack[];
  videoTracks: MP4VideoTrack[];
}

export type MP4ArrayBuffer = ArrayBuffer & { fileStart: number };

export interface MP4File {
  onMoovStart?: () => void;
  onReady?: (info: MP4Info) => void;
  onError?: (e: string) => void;
  onSamples?: (id: number, user: any, samples: Sample[]) => void;

  appendBuffer(data: MP4ArrayBuffer): number;
  start(): void;
  stop(): void;
  flush(): void;

  setExtractionOptions(id: number, user: any, options: ExtractionOptions): void;
}

export function createFile(): MP4File;

export interface Sample {
  number: number;
  track_id: number;
  timescale: number;
  description_index: number;
  description: {
    avcC?: BoxParser.avcCBox; // h.264
    hvcC?: BoxParser.hvcCBox; // hevc
    vpcC?: BoxParser.vpcCBox; // vp9
    av1C?: BoxParser.av1CBox; // av1
  };
  data: ArrayBuffer;
  size: number;
  alreadyRead?: number;
  duration: number;
  cts: number;
  dts: number;
  is_sync: boolean;
  is_leading?: number;
  depends_on?: number;
  is_depended_on?: number;
  has_redundancy?: number;
  degradation_priority?: number;
  offset?: number;
  subsamples?: any;
}

export interface ExtractionOptions {
  nbSamples: number;
}

export class DataStream {
  // WARNING, the default is little endian, which is not what MP4 uses.
  constructor(buffer?: ArrayBuffer, byteOffset?: number, endianness?: boolean);
  getPosition(): number;

  get byteLength(): number;
  get buffer(): ArrayBuffer;
  set buffer(v: ArrayBuffer);
  get byteOffset(): number;
  set byteOffset(v: number);
  get dataView(): DataView;
  set dataView(v: DataView);

  seek(pos: number): void;
  isEof(): boolean;

  mapFloat32Array(length: number, e?: boolean): any;
  mapFloat64Array(length: number, e?: boolean): any;
  mapInt16Array(length: number, e?: boolean): any;
  mapInt32Array(length: number, e?: boolean): any;
  mapInt8Array(length: number): any;
  mapUint16Array(length: number, e?: boolean): any;
  mapUint32Array(length: number, e?: boolean): any;
  mapUint8Array(length: number): any;

  readInt32Array(length: number, endianness?: boolean): Int32Array;
  readInt16Array(length: number, endianness?: boolean): Int16Array;
  readInt8Array(length: number): Int8Array;
  readUint32Array(length: number, endianness?: boolean): Uint32Array;
  readUint16Array(length: number, endianness?: boolean): Uint16Array;
  readUint8Array(length: number): Uint8Array;
  readFloat64Array(length: number, endianness?: boolean): Float64Array;
  readFloat32Array(length: number, endianness?: boolean): Float32Array;

  readInt32(endianness?: boolean): number;
  readInt16(endianness?: boolean): number;
  readInt8(): number;
  readUint32(endianness?: boolean): number;
  //readUint32Array(length: any, e: any): any
  readUint24(): number;
  readUint16(endianness?: boolean): number;
  readUint8(): number;
  //readUint64(): any
  readFloat32(endianness?: boolean): number;
  readFloat64(endianness?: boolean): number;
  //readCString(length: number): any
  //readString(length: number, encoding: any): any

  static endianness: boolean;

  memcpy(
    dst: ArrayBufferLike,
    dstOffset: number,
    src: ArrayBufferLike,
    srcOffset: number,
    byteLength: number
  ): void;

  // TODO I got bored porting all functions

  save(filename: string): void;
  shift(offset: number): void;

  writeInt32Array(arr: Int32Array, endianness?: boolean): void;
  writeInt16Array(arr: Int16Array, endianness?: boolean): void;
  writeInt8Array(arr: Int8Array): void;
  writeUint32Array(arr: Uint32Array, endianness?: boolean): void;
  writeUint16Array(arr: Uint16Array, endianness?: boolean): void;
  writeUint8Array(arr: Uint8Array): void;
  writeFloat64Array(arr: Float64Array, endianness?: boolean): void;
  writeFloat32Array(arr: Float32Array, endianness?: boolean): void;
  writeInt32(v: number, endianness?: boolean): void;
  writeInt16(v: number, endianness?: boolean): void;
  writeInt8(v: number): void;
  writeUint32(v: number, endianness?: boolean): void;
  writeUint16(v: number, endianness?: boolean): void;
  writeUint8(v: number): void;
  writeFloat32(v: number, endianness?: boolean): void;
  writeFloat64(v: number, endianness?: boolean): void;
  writeUCS2String(s: string, endianness?: boolean, length?: number): void;
  writeString(s: string, encoding?: string, length?: number): void;
  writeCString(s: string, length?: number): void;
  writeUint64(v: number): void;
  writeUint24(v: number): void;
  adjustUint32(pos: number, v: number): void;

  static LITTLE_ENDIAN: boolean;
  static BIG_ENDIAN: boolean;

  // TODO add correct types; these are exported by dts-gen
  readCString(length: any): any;
  readInt64(): any;
  readString(length: any, encoding: any): any;
  readUint64(): any;
  writeStruct(structDefinition: any, struct: any): void;
  writeType(t: any, v: any, struct: any): any;

  static arrayToNative(array: any, arrayIsLittleEndian: any): any;
  static flipArrayEndianness(array: any): any;
  static memcpy(
    dst: any,
    dstOffset: any,
    src: any,
    srcOffset: any,
    byteLength: any
  ): void;
  static nativeToEndian(array: any, littleEndian: any): any;
}

export interface TrackOptions {
  id?: number;
  type?: string;
  width?: number;
  height?: number;
  duration?: number;
  layer?: number;
  timescale?: number;
  media_duration?: number;
  language?: string;
  hdlr?: string;

  // video
  avcDecoderConfigRecord?: any;
  hevcDecoderConfigRecord?: any;

  // audio
  balance?: number;
  channel_count?: number;
  samplesize?: number;
  samplerate?: number;

  //captions
  namespace?: string;
  schema_location?: string;
  auxiliary_mime_types?: string;

  description?: BoxParser.Box;
  description_boxes?: BoxParser.Box[];

  default_sample_description_index_id?: number;
  default_sample_duration?: number;
  default_sample_size?: number;
  default_sample_flags?: number;
}

export interface FileOptions {
  brands?: string[];
  timescale?: number;
  rate?: number;
  duration?: number;
  width?: number;
}

export interface SampleOptions {
  sample_description_index?: number;
  duration?: number;
  cts?: number;
  dts?: number;
  is_sync?: boolean;
  is_leading?: number;
  depends_on?: number;
  is_depended_on?: number;
  has_redundancy?: number;
  degradation_priority?: number;
  subsamples?: any;
}

// TODO add the remaining functions
// TODO move to another module
export class ISOFile {
  constructor(stream?: DataStream);

  init(options?: FileOptions): ISOFile;
  addTrack(options?: TrackOptions): number;
  addSample(track: number, data: ArrayBuffer, options?: SampleOptions): Sample;

  createSingleSampleMoof(sample: Sample): BoxParser.moofBox;

  // helpers
  getTrackById(id: number): BoxParser.trakBox | undefined;
  getTrexById(id: number): BoxParser.trexBox | undefined;

  // boxes that are added to the root
  boxes: BoxParser.Box[];
  mdats: BoxParser.mdatBox[];
  moofs: BoxParser.moofBox[];

  ftyp?: BoxParser.ftypBox;
  moov?: BoxParser.moovBox;

  static writeInitializationSegment(
    ftyp: BoxParser.ftypBox,
    moov: BoxParser.moovBox,
    total_duration: number,
    sample_duration: number
  ): ArrayBuffer;

  // TODO add correct types; these are exported by dts-gen
  add(name: any): any;
  addBox(box: any): any;
  appendBuffer(ab: any, last: any): any;
  buildSampleLists(): void;
  buildTrakSampleLists(trak: any): void;
  checkBuffer(ab: any): any;
  createFragment(track_id: any, sampleNumber: any, stream_: any): any;
  equal(b: any): any;
  flattenItemInfo(): void;
  flush(): void;
  getAllocatedSampleDataSize(): any;
  getBox(type: any): any;
  getBoxes(type: any, returnEarly: any): any;
  getBuffer(): any;
  getCodecs(): any;
  getInfo(): any;
  getItem(item_id: any): any;
  getMetaHandler(): any;
  getPrimaryItem(): any;
  getSample(trak: any, sampleNum: any): any;
  getTrackSample(track_id: any, number: any): any;
  getTrackSamplesInfo(track_id: any): any;
  hasIncompleteMdat(): any;
  hasItem(name: any): any;
  initializeSegmentation(): any;
  itemToFragmentedTrackFile(_options: any): any;
  parse(): void;
  print(output: any): void;
  processIncompleteBox(ret: any): any;
  processIncompleteMdat(): any;
  processItems(callback: any): void;
  processSamples(last: any): void;
  releaseItem(item_id: any): any;
  releaseSample(trak: any, sampleNum: any): any;
  releaseUsedSamples(id: any, sampleNum: any): void;
  resetTables(): void;
  restoreParsePosition(): any;
  save(name: any): void;
  saveParsePosition(): void;
  seek(time: any, useRap: any): any;
  seekTrack(time: any, useRap: any, trak: any): any;
  setExtractionOptions(id: any, user: any, options: any): void;
  setSegmentOptions(id: any, user: any, options: any): void;
  start(): void;
  stop(): void;
  unsetExtractionOptions(id: any): void;
  unsetSegmentOptions(id: any): void;
  updateSampleLists(): void;
  updateUsedBytes(box: any, ret: any): void;
  write(outstream: any): void;

  static initSampleGroups(
    trak: any,
    traf: any,
    sbgps: any,
    trak_sgpds: any,
    traf_sgpds: any
  ): void;
  static process_sdtp(sdtp: any, sample: any, number: any): void;
  static setSampleGroupProperties(
    trak: any,
    sample: any,
    sample_number: any,
    sample_groups_info: any
  ): void;
}

export namespace BoxParser {
  export class Box {
    size?: number;
    data?: Uint8Array;

    constructor(type?: string, size?: number);

    add(name: string): Box;
    addBox(box: Box): Box;
    set(name: string, value: any): void;
    addEntry(value: string, prop?: string): void;
    printHeader(output: any): void;
    write(stream: DataStream): void;
    writeHeader(stream: DataStream, msg?: string): void;
    computeSize(): void;

    // TODO add types for these
    parse(stream: any): void;
    parseDataAndRewind(stream: any): void;
    parseLanguage(stream: any): void;
    print(output: any): void;
  }

  // TODO finish add types for these classes
  export class AudioSampleEntry extends SampleEntry {
    constructor(type: any, size: any);

    getChannelCount(): any;
    getSampleRate(): any;
    getSampleSize(): any;
    isAudio(): any;
    parse(stream: any): void;
    write(stream: any): void;
  }

  export class CoLLBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class ContainerBox extends Box {
    constructor(type: any, size: any, uuid: any);

    parse(stream: any): void;
    print(output: any): void;
    write(stream: any): void;
  }

  export class FullBox extends Box {
    constructor(type: any, size: any, uuid: any);

    parse(stream: any): void;
    parseDataAndRewind(stream: any): void;
    parseFullHeader(stream: any): void;
    printHeader(output: any): void;
    writeHeader(stream: any): void;
  }

  export class HintSampleEntry extends SampleEntry {
    constructor(type: any, size: any);
  }

  export class MetadataSampleEntry extends SampleEntry {
    constructor(type: any, size: any);

    isMetadata(): any;
  }

  export class OpusSampleEntry extends SampleEntry {
    constructor(size: any);
  }

  export class SampleEntry extends Box {
    constructor(type: any, size: any, hdr_size: any, start: any);

    getChannelCount(): any;
    getCodec(): any;
    getHeight(): any;
    getSampleRate(): any;
    getSampleSize(): any;
    getWidth(): any;
    isAudio(): any;
    isHint(): any;
    isMetadata(): any;
    isSubtitle(): any;
    isVideo(): any;
    parse(stream: any): void;
    parseDataAndRewind(stream: any): void;
    parseFooter(stream: any): void;
    parseHeader(stream: any): void;
    write(stream: any): void;
    writeFooter(stream: any): void;
    writeHeader(stream: any): void;
  }

  export class SampleGroupEntry {
    constructor(type: any);

    parse(stream: any): void;
    write(stream: any): void;
  }

  export class SingleItemTypeReferenceBox extends ContainerBox {
    constructor(type: any, size: any, hdr_size: any, start: any);

    parse(stream: any): void;
  }

  export class SingleItemTypeReferenceBoxLarge {
    constructor(type: any, size: any, hdr_size: any, start: any);

    parse(stream: any): void;
  }

  export class SmDmBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class SubtitleSampleEntry extends SampleEntry {
    constructor(type: any, size: any);

    isSubtitle(): any;
  }

  export class SystemSampleEntry extends SampleEntry {
    constructor(type: any, size: any);
  }

  export class TextSampleEntry extends SampleEntry {
    constructor(type: any, size: any);
  }

  export class TrackGroupTypeBox extends FullBox {
    constructor(type: any, size: any);

    parse(stream: any): void;
  }

  export class TrackReferenceTypeBox extends ContainerBox {
    constructor(type: any, size: any, hdr_size: any, start: any);

    parse(stream: any): void;

    write(stream: any): void;
  }

  export class VisualSampleEntry extends SampleEntry {
    constructor(type: any, size: any);

    getHeight(): any;
    getWidth(): any;
    isVideo(): any;
    parse(stream: any): void;
    write(stream: any): void;
  }

  export class a1lxBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class a1opBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class alstSampleGroupEntry extends SampleGroupEntry {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class auxCBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class av01SampleEntry extends SampleEntry {
    constructor(size: any);

    getCodec(): any;
  }

  export class av1CBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class avc1SampleEntry extends SampleEntry {
    constructor(size: any);

    getCodec(): any;
  }

  export class avc2SampleEntry extends SampleEntry {
    constructor(size: any);

    getCodec(): any;
  }

  export class avc3SampleEntry extends SampleEntry {
    constructor(size: any);

    getCodec(): any;
  }

  export class avc4SampleEntry extends SampleEntry {
    constructor(size: any);

    getCodec(): any;
  }

  export class avcCBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
    write(stream: any): void;
  }

  export class avllSampleGroupEntry extends SampleGroupEntry {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class avssSampleGroupEntry extends SampleGroupEntry {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class btrtBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class bxmlBox extends FullBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class clapBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class clefBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class clliBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class co64Box extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
    write(stream: any): void;
  }

  export class colrBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class cprtBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class cslgBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
    write(stream: any): void;
  }

  export class cttsBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
    unpack(samples: any): void;
    write(stream: any): void;
  }

  export class dOpsBox extends ContainerBox {
    constructor(size?: number);

    parse(stream: DataStream): void;

    Version: number;
    OutputChannelCount: number;
    PreSkip: number;
    InputSampleRate: number;
    OutputGain: number;
    ChannelMappingFamily: number;

    // When channelMappingFamily != 0
    StreamCount?: number;
    CoupledCount?: number;
    ChannelMapping?: number[];
  }

  export class dac3Box extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class dec3Box extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class dfLaBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class dimmBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class dinfBox extends ContainerBox {
    constructor(size: any);
  }

  export class dmaxBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class dmedBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class drefBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
    write(stream: any): void;
  }

  export class drepBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class dtrtSampleGroupEntry extends SampleGroupEntry {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class edtsBox extends ContainerBox {
    constructor(size: any);
  }

  export class elngBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
    write(stream: any): void;
  }

  export class elstBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
    write(stream: any): void;
  }

  export class emsgBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
    write(stream: any): void;
  }

  export class encaSampleEntry extends SampleEntry {
    constructor(size: any);
  }

  export class encmSampleEntry extends SampleEntry {
    constructor(size: any);
  }

  export class encsSampleEntry extends SampleEntry {
    constructor(size: any);
  }

  export class enctSampleEntry extends SampleEntry {
    constructor(size: any);
  }

  export class encuSampleEntry extends SampleEntry {
    constructor(size: any);
  }

  export class encvSampleEntry extends SampleEntry {
    constructor(size: any);
  }

  export class enofBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class esdsBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class fielBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class freeBox extends Box {
    constructor(size: any);
  }

  export class frmaBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class ftypBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
    write(stream: any): void;
  }

  export class hdlrBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
    write(stream: any): void;
  }

  export class hev1SampleEntry extends SampleEntry {
    constructor(size: any);

    getCodec(): any;
  }

  export class hinfBox extends ContainerBox {
    constructor(size: any);
  }

  export class hmhdBox extends FullBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class hntiBox extends ContainerBox {
    constructor(size: any);
  }

  export class hvc1SampleEntry extends SampleEntry {
    constructor(size: any);

    getCodec(): any;
  }

  export class hvcCBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class idatBox extends Box {
    constructor(size: any);
  }

  export class iinfBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class ilocBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class imirBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class infeBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class iodsBox extends FullBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class ipcoBox extends ContainerBox {
    constructor(size: any);
  }

  export class ipmaBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class iproBox extends FullBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class iprpBox extends ContainerBox {
    constructor(size: any);
    ipmas: ipmaBox[];
  }

  export class irefBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class irotBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class ispeBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class kindBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;

    write(stream: any): void;
  }

  export class levaBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class lselBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class maxrBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class mdatBox extends Box {
    constructor(size: any);
  }

  export class mdcvBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class mdhdBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;

    write(stream: any): void;
  }

  export class mdiaBox extends ContainerBox {
    constructor(size: any);
  }

  export class mecoBox extends Box {
    constructor(size: any);
  }

  export class mehdBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;

    write(stream: any): void;
  }

  export class mereBox extends FullBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class metaBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class mettSampleEntry extends SampleEntry {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class metxSampleEntry extends SampleEntry {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class mfhdBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;

    write(stream: any): void;
  }

  export class mfraBox extends ContainerBox {
    constructor(size: any);
    tfras: tfraBox[];
  }

  export class mfroBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class minfBox extends ContainerBox {
    constructor(size: any);
  }

  export class moofBox extends ContainerBox {
    constructor(size: any);
    trafs: trafBox[];
  }

  export class moovBox extends ContainerBox {
    constructor(size: any);
    traks: trakBox[];
    psshs: psshBox[];
  }

  export class mp4aSampleEntry extends SampleEntry {
    constructor(size: any);

    getCodec(): any;
  }

  export class msrcTrackGroupTypeBox extends ContainerBox {
    constructor(size: any);
  }

  export class mvexBox extends ContainerBox {
    constructor(size: any);

    trexs: trexBox[];
  }

  export class mvhdBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
    print(output: any): void;
    write(stream: any): void;
  }

  export class mvifSampleGroupEntry extends SampleGroupEntry {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class nmhdBox extends FullBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class npckBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class numpBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class padbBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class paspBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class paylBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class paytBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class pdinBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class pitmBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class pixiBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class pmaxBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class prftBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class profBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class prolSampleGroupEntry extends SampleGroupEntry {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class psshBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class rashSampleGroupEntry extends SampleGroupEntry {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class rinfBox extends ContainerBox {
    constructor(size: any);
  }

  export class rollSampleGroupEntry extends SampleGroupEntry {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class saioBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class saizBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class sbgpBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;

    write(stream: any): void;
  }

  export class sbttSampleEntry extends SampleEntry {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class schiBox extends ContainerBox {
    constructor(size: any);
  }

  export class schmBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class scifSampleGroupEntry extends SampleGroupEntry {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class scnmSampleGroupEntry extends SampleGroupEntry {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class sdtpBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class seigSampleGroupEntry extends SampleGroupEntry {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class sencBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class sgpdBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
    write(stream: any): void;
  }

  export class sidxBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
    write(stream: any): void;
  }

  export class sinfBox extends ContainerBox {
    constructor(size: any);
  }

  export class skipBox extends Box {
    constructor(size: any);
  }

  export class smhdBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
    write(stream: any): void;
  }

  export class ssixBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class stblBox extends ContainerBox {
    constructor(size: any);

    sgpds: sgpdBox[];
    sbgps: sbgpBox[];
  }

  export class stcoBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
    unpack(samples: any): void;
    write(stream: any): void;
  }

  export class stdpBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class sthdBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class stppSampleEntry extends SampleEntry {
    constructor(size: any);

    parse(stream: any): void;
    write(stream: any): void;
  }

  export class strdBox extends ContainerBox {
    constructor(size: any);
  }

  export class striBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class strkBox extends Box {
    constructor(size: any);
  }

  export class stsaSampleGroupEntry extends SampleGroupEntry {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class stscBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
    unpack(samples: any): void;
    write(stream: any): void;
  }

  export class stsdBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
    write(stream: any): void;
  }

  export class stsgBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class stshBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
    write(stream: any): void;
  }

  export class stssBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
    write(stream: any): void;
  }

  export class stszBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
    unpack(samples: any): void;
    write(stream: any): void;
  }

  export class sttsBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
    unpack(samples: any): void;
    write(stream: any): void;
  }

  export class stviBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class stxtSampleEntry extends SampleEntry {
    constructor(size: any);

    getCodec(): any;
    parse(stream: any): void;
  }

  export class stypBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class stz2Box extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class subsBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class syncSampleGroupEntry extends SampleGroupEntry {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class taptBox extends ContainerBox {
    constructor(size: any);
  }

  export class teleSampleGroupEntry extends SampleGroupEntry {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class tencBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class tfdtBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
    write(stream: any): void;
  }

  export class tfhdBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
    write(stream: any): void;
  }

  export class tfraBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class tkhdBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
    print(output: any): void;
    write(stream: any): void;
  }

  export class tmaxBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class tminBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class totlBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class tpayBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class tpylBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class trafBox extends ContainerBox {
    constructor(size: any);
    truns: trunBox[];
    sgpd: sgpdBox[];
    sbgp: sbgpBox[];
  }

  export class trakBox extends ContainerBox {
    constructor(size: any);
  }

  export class trefBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class trepBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class trexBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
    write(stream: any): void;
  }

  export class trgrBox extends ContainerBox {
    constructor(size: any);
  }

  export class trpyBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class trunBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
    write(stream: any): void;
  }

  export class tsasSampleGroupEntry extends SampleGroupEntry {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class tsclSampleGroupEntry extends SampleGroupEntry {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class tselBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class tx3gSampleEntry extends SampleEntry {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class txtCBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class udtaBox extends ContainerBox {
    constructor(size: any);
    kinds: kindBox[];
  }

  export class viprSampleGroupEntry extends SampleGroupEntry {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class vmhdBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
    write(stream: any): void;
  }

  export class vp08SampleEntry extends SampleEntry {
    constructor(size: any);

    getCodec(): any;
  }

  export class vp09SampleEntry extends SampleEntry {
    constructor(size: any);

    getCodec(): any;
  }

  export class vpcCBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class vttCBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class vttcBox extends ContainerBox {
    constructor(size: any);
  }

  export class vvc1SampleEntry extends SampleEntry {
    constructor(size: any);

    getCodec(): any;
  }

  export class vvcCBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class vvcNSampleEntry extends SampleEntry {
    constructor(size: any);
  }

  export class vvi1SampleEntry extends SampleEntry {
    constructor(size: any);

    getCodec(): any;
  }

  export class vvnCBox extends ContainerBox {
    constructor(size: any);

    parse(stream: any): void;
  }

  export class vvs1SampleEntry extends SampleEntry {
    constructor(size: any);
  }

  export class wvttSampleEntry extends SampleEntry {
    constructor(size: any);

    parse(stream: any): void;
  }

  export const BASIC_BOXES: string[];
  export const CONTAINER_BOXES: string[][];
  export const DIFF_BOXES_PROP_NAMES: string[];
  export const DIFF_PRIMITIVE_ARRAY_PROP_NAMES: string[];
  export const ERR_INVALID_DATA: number;
  export const ERR_NOT_ENOUGH_DATA: number;
  export const FULL_BOXES: string[];
  export const OK: number;
  export const SAMPLE_ENTRY_TYPE_AUDIO: string;
  export const SAMPLE_ENTRY_TYPE_HINT: string;
  export const SAMPLE_ENTRY_TYPE_METADATA: string;
  export const SAMPLE_ENTRY_TYPE_SUBTITLE: string;
  export const SAMPLE_ENTRY_TYPE_SYSTEM: string;
  export const SAMPLE_ENTRY_TYPE_TEXT: string;
  export const SAMPLE_ENTRY_TYPE_VISUAL: string;
  export const TFHD_FLAG_BASE_DATA_OFFSET: number;
  export const TFHD_FLAG_DEFAULT_BASE_IS_MOOF: number;
  export const TFHD_FLAG_DUR_EMPTY: number;
  export const TFHD_FLAG_SAMPLE_DESC: number;
  export const TFHD_FLAG_SAMPLE_DUR: number;
  export const TFHD_FLAG_SAMPLE_FLAGS: number;
  export const TFHD_FLAG_SAMPLE_SIZE: number;
  export const TKHD_FLAG_ENABLED: number;
  export const TKHD_FLAG_IN_MOVIE: number;
  export const TKHD_FLAG_IN_PREVIEW: number;
  export const TRUN_FLAGS_CTS_OFFSET: number;
  export const TRUN_FLAGS_DATA_OFFSET: number;
  export const TRUN_FLAGS_DURATION: number;
  export const TRUN_FLAGS_FIRST_FLAG: number;
  export const TRUN_FLAGS_FLAGS: number;
  export const TRUN_FLAGS_SIZE: number;
  export const UUIDs: string[];
  export const boxCodes: string[];
  export const containerBoxCodes: any[];
  export const fullBoxCodes: any[];

  export const sampleEntryCodes: {
    Audio: string[];
    Hint: any[];
    Metadata: string[];
    Subtitle: string[];
    System: string[];
    Text: string[];
    Visual: string[];
  };

  export const sampleGroupEntryCodes: any[];

  export const trackGroupTypes: any[];

  export function addSubBoxArrays(subBoxNames: any): void;
  export function boxEqual(box_a: any, box_b: any): any;
  export function boxEqualFields(box_a: any, box_b: any): any;
  export function createBoxCtor(type: any, parseMethod: any): void;
  export function createContainerBoxCtor(
    type: any,
    parseMethod: any,
    subBoxNames: any
  ): void;
  export function createEncryptedSampleEntryCtor(
    mediaType: any,
    type: any,
    parseMethod: any
  ): void;
  export function createFullBoxCtor(type: any, parseMethod: any): void;
  export function createMediaSampleEntryCtor(
    mediaType: any,
    parseMethod: any,
    subBoxNames: any
  ): void;
  export function createSampleEntryCtor(
    mediaType: any,
    type: any,
    parseMethod: any,
    subBoxNames: any
  ): void;
  export function createSampleGroupCtor(type: any, parseMethod: any): void;
  export function createTrackGroupCtor(type: any, parseMethod: any): void;
  export function createUUIDBox(
    uuid: any,
    isFullBox: any,
    isContainerBox: any,
    parseMethod: any
  ): void;
  export function decimalToHex(d: any, padding: any): any;
  export function initialize(): void;
  export function parseHex16(stream: any): any;
  export function parseOneBox(
    stream: any,
    headerOnly: any,
    parentSize: any
  ): any;
  export function parseUUID(stream: any): any;

  /* ???
	namespace UUIDBoxes {
		export class a2394f525a9b4f14a2446c427c648df4 {
			constructor(size: any)
		}

		export class a5d40b30e81411ddba2f0800200c9a66 {
			constructor(size: any)

			parse(stream: any): void
		}

		export class d08a4f1810f34a82b6c832d8aba183d3 {
			constructor(size: any)

			parse(stream: any): void
		}

		export class d4807ef2ca3946958e5426cb9e46a79f {
			constructor(size: any)

			parse(stream: any): void
		}
	}
	*/
}

// TODO Add types for the remaining classes found via dts-gen
export class MP4BoxStream {
  constructor(arrayBuffer: any);

  getEndPosition(): any;
  getLength(): any;
  getPosition(): any;
  isEos(): any;
  readAnyInt(size: any, signed: any): any;
  readCString(): any;
  readInt16(): any;
  readInt16Array(length: any): any;
  readInt32(): any;
  readInt32Array(length: any): any;
  readInt64(): any;
  readInt8(): any;
  readString(length: any): any;
  readUint16(): any;
  readUint16Array(length: any): any;
  readUint24(): any;
  readUint32(): any;
  readUint32Array(length: any): any;
  readUint64(): any;
  readUint8(): any;
  readUint8Array(length: any): any;
  seek(pos: any): any;
}

export class MultiBufferStream {
  constructor(buffer: any);

  addUsedBytes(nbBytes: any): void;
  cleanBuffers(): void;
  findEndContiguousBuf(inputindex: any): any;
  findPosition(fromStart: any, filePosition: any, markAsUsed: any): any;
  getEndFilePositionAfter(pos: any): any;
  getEndPosition(): any;
  getLength(): any;
  getPosition(): any;
  initialized(): any;
  insertBuffer(ab: any): void;
  logBufferLevel(info: any): void;
  mergeNextBuffer(): any;
  reduceBuffer(buffer: any, offset: any, newLength: any): any;
  seek(filePosition: any, fromStart: any, markAsUsed: any): any;
  setAllUsedBytes(): void;
}

export class Textin4Parser {
  constructor();

  parseConfig(data: any): any;
  parseSample(sample: any): any;
}

export class XMLSubtitlein4Parser {
  constructor();

  parseSample(sample: any): any;
}

export function MPEG4DescriptorParser(): any;

export namespace BoxParser {}

export namespace Log {
  export const LOG_LEVEL_ERROR = 4;
  export const LOG_LEVEL_WARNING = 3;
  export const LOG_LEVEL_INFO = 2;
  export const LOG_LEVEL_DEBUG = 1;

  export function debug(module: any, msg: any): void;
  export function error(module: any, msg: any): void;
  export function getDurationString(duration: any, _timescale: any): any;
  export function info(module: any, msg: any): void;
  export function log(module: any, msg: any): void;
  export function printRanges(ranges: any): any;
  export function setLogLevel(level: any): void;
  export function warn(module: any, msg: any): void;
}

declare var FLAGS: Flags;
declare global {
  interface Window {
    FLAGS: Flags;
  }
}
