// Copyright (c) 2021 Giorgos Vougioukas
//
// The license can be found in the LICENSE file.

#ifndef _RSI_DATA_BANK_H_
#define _RSI_DATA_BANK_H_

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

#include "third_party/libebur128/ebur128/ebur128.h"

#include "RSI/sample_format.h"

#include "WDL/wdltypes.h"
#include "WDL/heapbuf.h"
#include "WDL/ptrlist.h"
#include "WDL/mutex.h"
#include "WDL/lice/lice.h"

class RSI_DataBankSlot
{
public:
  RSI_DataBankSlot();
  ~RSI_DataBankSlot();

  void Reset();
  void PrepareIndexes();
  bool IsPrepared() const;
  void Seek(double time);
  double GetLength() const;
  double GetPosition() const;
  void Allocate(double length);
  void AddSamples(SAM *buffer, int buffer_size);
  int GetSamples(SAM *buffer, int buffer_size);
  int GetSamplesReverse(SAM *buffer, int buffer_size);

  bool IsEBUR128Enabled() const;
  int GetEBUR128Mode() const;
  double GetEBUR128Reference() const;
  double GetEBUR128Momentary() const;
  double GetEBUR128Shortterm() const;
  double GetEBUR128Integrated() const;
  double GetEBUR128Range() const;
  double GetEBUR128SamplePeak() const;
  double GetEBUR128TruePeak() const;
  double GetEBUR128Gain() const;
  bool IsEBUR128DowndwardOnly() const;

  void GetWaveformA(LICE_IBitmap **bitmap, int *peak_points) const;
  void GetWaveformB(LICE_IBitmap **bitmap, int *peak_points) const;
  void SetWaveformA(int width, int height);
  void SetWaveformB(int width, int height);

private:
  unsigned char *m_data;
  WDL_INT64 m_size;
  WDL_INT64 m_capacity;
  WDL_INT64 m_index;
  WDL_INT64 m_indexrev;
  double m_samplerate;
  int m_antidotefmt;
  double m_length;
  int m_channels;
  int m_bitspersample;
  WDL_HeapBuf m_rawbuf;
  WDL_Mutex m_mutex;
  ebur128_state *m_stt;
  bool m_ebur128;
  double m_ebur128ref;
  int m_ebur128mode;
  double m_ebur128momentary;
  double m_ebur128shortterm;
  int m_ebur128momentarywindow;
  int m_ebur128shorttermwindow;
  double m_ebur128integrated;
  double m_ebur128range;
  double m_ebur128samplepeak;
  double m_ebur128truepeak;
  double m_ebur128gain;
  bool m_ebur128downwardonly;
  int m_momentarywindow;
  int m_shorttermwindow;
  bool m_prepared;
  int m_pps;
  int m_pt;
  float *m_peak;
  int m_peakpoints;
  WDL_INT64 m_peaksize;
  WDL_INT64 m_peakcapacity;
  WDL_INT64 m_peakstep;
  float m_avgsam;
  int m_samni;
  LICE_IBitmap *m_waveforma;
  LICE_IBitmap *m_waveformb;
};

class RSI_DataBank
{
public:
  RSI_DataBank();
  ~RSI_DataBank();

  RSI_DataBankSlot *GetSlot(int index) const;
  int GetSize() const;

private:
  WDL_PtrList<RSI_DataBankSlot> m_slots;
};

#endif // _RSI_DATA_BANK_H_
