#pragma once

#include "AudioTools/AudioCodecs/AudioCodecsBase.h"
#if defined(ARDUINO) && !defined(IS_MIN_DESKTOP)
#include "Print.h"
#endif

namespace audio_tools {

/**
 * @brief Dummy Decoder which just copies the provided data to the output.
 * You can define if it is PCM data.
 * @ingroup codecs
 * @ingroup decoder
 * @author Phil Schatzmann
 * @copyright GPLv3
 */
class CopyDecoder : public AudioDecoder {
public:

  CopyDecoder(bool isPcm = false){
    is_pcm = isPcm;
  }

  CopyDecoder(Print &out_stream) { TRACED(); pt_print=&out_stream; }

  CopyDecoder(Print &out_stream, AudioInfoSupport &bi) {pt_print=&out_stream;}

  ~CopyDecoder() {}

  virtual void setOutput(Print &out_stream) {pt_print=&out_stream;}

  bool begin() { return true; }

  void end() {}

  size_t write(const uint8_t *data, size_t len) { 
    TRACED();
    if (pt_print == nullptr) {
      LOGE("No output stream defined for CopyDecoder");
      return 0;
    }
    return pt_print->write((uint8_t*)data,len);
  }

  operator bool() { return true; }

  /// The result is encoded data - by default this is false
  virtual bool isResultPCM() { return is_pcm;} 

  /// Defines that the source and therefor the result is also PCM data
  void setResultPCM(bool pcm){ is_pcm = pcm;}

protected:
  Print *pt_print=nullptr;
  bool is_pcm = false;
};

/**
 * @brief Dummy Encoder which just copies the provided data to the output
 * @ingroup codecs
 * @ingroup encoder
 * @author Phil Schatzmann
 * @copyright GPLv3
 */
class CopyEncoder : public AudioEncoder {
public:
  CopyEncoder() { TRACED(); }

  CopyEncoder(Print &out_stream) { TRACED(); pt_print=&out_stream; }

  CopyEncoder(Print &out_stream, AudioInfoSupport &bi) {pt_print=&out_stream;}

  ~CopyEncoder() {}

  virtual void setOutput(Print &out_stream) {pt_print=&out_stream;}

  bool begin() { return true;}

  void end() {}

  size_t write(const uint8_t *data, size_t len) { 
    if (pt_print == nullptr) {
      LOGE("No output stream defined for CopyDecoder");
      return 0;
    }
    return pt_print->write((uint8_t*)data,len); 
  }

  operator bool() { return true; }

  /// Provides the mime type of the encoded data
  const char *mime() {return mime_type;}

  /// Defines the mime type
  void setMime(const char *mime) { mime_type = mime; }


protected:
  Print *pt_print=nullptr;
  const char *mime_type = "audio/pcm";
};

/// @brief Alias for CopyEncoder to handle PCM audio encoding (no actual encoding)
/// @ingroup codecs
using PCMEncoder = CopyEncoder;

/// @brief Alias for CopyDecoder to handle PCM audio decoding (no actual decoding)
/// @ingroup codecs
using PCMDecoder = CopyDecoder;

} // namespace audio_tools

