/*
 *  Copyright (c) 2013 The WebRTC 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.
 */

#include "test/fake_audio_device.h"

#include <algorithm>
#include <utility>

#include "common_audio/wav_file.h"
#include "rtc_base/checks.h"
#include "system_wrappers/include/event_wrapper.h"

namespace webrtc {

namespace {

constexpr int kFrameLengthMs = 10;
constexpr int kFramesPerSecond = 1000 / kFrameLengthMs;

class WavFileReader final : public test::FakeAudioDevice::Capturer {
 public:
  WavFileReader(std::string filename, int sampling_frequency_in_hz)
      : sampling_frequency_in_hz_(sampling_frequency_in_hz),
        wav_reader_(filename) {
    RTC_CHECK_EQ(wav_reader_.sample_rate(), sampling_frequency_in_hz);
    RTC_CHECK_EQ(wav_reader_.num_channels(), 1);
  }

  int SamplingFrequency() const override {
    return sampling_frequency_in_hz_;
  }

  bool Capture(rtc::BufferT<int16_t>* buffer) override {
    buffer->SetData(
        test::FakeAudioDevice::SamplesPerFrame(sampling_frequency_in_hz_),
        [&](rtc::ArrayView<int16_t> data) {
      return wav_reader_.ReadSamples(data.size(), data.data());
    });
    return buffer->size() > 0;
  }

 private:
  int sampling_frequency_in_hz_;
  WavReader wav_reader_;
};

class WavFileWriter final : public test::FakeAudioDevice::Renderer {
 public:
  WavFileWriter(std::string filename, int sampling_frequency_in_hz)
      : sampling_frequency_in_hz_(sampling_frequency_in_hz),
        wav_writer_(filename, sampling_frequency_in_hz, 1) {}

  int SamplingFrequency() const override {
    return sampling_frequency_in_hz_;
  }

  bool Render(rtc::ArrayView<const int16_t> data) override {
    wav_writer_.WriteSamples(data.data(), data.size());
    return true;
  }

 private:
  int sampling_frequency_in_hz_;
  WavWriter wav_writer_;
};

class BoundedWavFileWriter : public test::FakeAudioDevice::Renderer {
 public:
  BoundedWavFileWriter(std::string filename, int sampling_frequency_in_hz)
      : sampling_frequency_in_hz_(sampling_frequency_in_hz),
        wav_writer_(filename, sampling_frequency_in_hz, 1),
        silent_audio_(test::FakeAudioDevice::SamplesPerFrame(
            sampling_frequency_in_hz), 0),
        started_writing_(false),
        trailing_zeros_(0) {}

  int SamplingFrequency() const override {
    return sampling_frequency_in_hz_;
  }

  bool Render(rtc::ArrayView<const int16_t> data) override {
    const int16_t kAmplitudeThreshold = 5;

    const int16_t* begin = data.begin();
    const int16_t* end = data.end();
    if (!started_writing_) {
      // Cut off silence at the beginning.
      while (begin < end) {
        if (std::abs(*begin) > kAmplitudeThreshold) {
          started_writing_ = true;
          break;
        }
        ++begin;
      }
    }
    if (started_writing_) {
      // Cut off silence at the end.
      while (begin < end) {
        if (*(end - 1) != 0) {
          break;
        }
        --end;
      }
      if (begin < end) {
        // If it turns out that the silence was not final, need to write all the
        // skipped zeros and continue writing audio.
        while (trailing_zeros_ > 0) {
          const size_t zeros_to_write = std::min(trailing_zeros_,
                                                 silent_audio_.size());
          wav_writer_.WriteSamples(silent_audio_.data(), zeros_to_write);
          trailing_zeros_ -= zeros_to_write;
        }
        wav_writer_.WriteSamples(begin, end - begin);
      }
      // Save the number of zeros we skipped in case this needs to be restored.
      trailing_zeros_ += data.end() - end;
    }
    return true;
  }

 private:
  int sampling_frequency_in_hz_;
  WavWriter wav_writer_;
  std::vector<int16_t> silent_audio_;
  bool started_writing_;
  size_t trailing_zeros_;
};


class DiscardRenderer final : public test::FakeAudioDevice::Renderer {
 public:
  explicit DiscardRenderer(int sampling_frequency_in_hz)
      : sampling_frequency_in_hz_(sampling_frequency_in_hz) {}

  int SamplingFrequency() const override {
    return sampling_frequency_in_hz_;
  }

  bool Render(rtc::ArrayView<const int16_t> data) override {
    return true;
  }

 private:
  int sampling_frequency_in_hz_;
};

}  // namespace
namespace test {

// Assuming 10ms audio packets.
FakeAudioDevice::PulsedNoiseCapturer::PulsedNoiseCapturer(
    int16_t max_amplitude,
    int sampling_frequency_in_hz)
    : sampling_frequency_in_hz_(sampling_frequency_in_hz),
      fill_with_zero_(false),
      random_generator_(1),
      max_amplitude_(max_amplitude) {
  RTC_DCHECK_GT(max_amplitude, 0);
}

bool FakeAudioDevice::PulsedNoiseCapturer::Capture(
    rtc::BufferT<int16_t>* buffer) {
  fill_with_zero_ = !fill_with_zero_;
  int16_t max_amplitude;
  {
    rtc::CritScope cs(&lock_);
    max_amplitude = max_amplitude_;
  }
  buffer->SetData(FakeAudioDevice::SamplesPerFrame(sampling_frequency_in_hz_),
                  [&](rtc::ArrayView<int16_t> data) {
                    if (fill_with_zero_) {
                      std::fill(data.begin(), data.end(), 0);
                    } else {
                      std::generate(data.begin(), data.end(), [&]() {
                        return random_generator_.Rand(-max_amplitude,
                                                      max_amplitude);
                      });
                    }
                    return data.size();
                  });
  return true;
}

void FakeAudioDevice::PulsedNoiseCapturer::SetMaxAmplitude(int16_t amplitude) {
  rtc::CritScope cs(&lock_);
  max_amplitude_ = amplitude;
}

size_t FakeAudioDevice::SamplesPerFrame(int sampling_frequency_in_hz) {
  return rtc::CheckedDivExact(sampling_frequency_in_hz, kFramesPerSecond);
}

std::unique_ptr<FakeAudioDevice::PulsedNoiseCapturer>
FakeAudioDevice::CreatePulsedNoiseCapturer(int16_t max_amplitude,
                                           int sampling_frequency_in_hz) {
  return std::unique_ptr<FakeAudioDevice::PulsedNoiseCapturer>(
      new PulsedNoiseCapturer(max_amplitude, sampling_frequency_in_hz));
}

std::unique_ptr<FakeAudioDevice::Capturer> FakeAudioDevice::CreateWavFileReader(
    std::string filename, int sampling_frequency_in_hz) {
  return std::unique_ptr<FakeAudioDevice::Capturer>(
      new WavFileReader(filename, sampling_frequency_in_hz));
}

std::unique_ptr<FakeAudioDevice::Capturer> FakeAudioDevice::CreateWavFileReader(
    std::string filename) {
  int sampling_frequency_in_hz = WavReader(filename).sample_rate();
  return std::unique_ptr<FakeAudioDevice::Capturer>(
      new WavFileReader(filename, sampling_frequency_in_hz));
}

std::unique_ptr<FakeAudioDevice::Renderer> FakeAudioDevice::CreateWavFileWriter(
    std::string filename, int sampling_frequency_in_hz) {
  return std::unique_ptr<FakeAudioDevice::Renderer>(
      new WavFileWriter(filename, sampling_frequency_in_hz));
}

std::unique_ptr<FakeAudioDevice::Renderer>
    FakeAudioDevice::CreateBoundedWavFileWriter(
        std::string filename, int sampling_frequency_in_hz) {
  return std::unique_ptr<FakeAudioDevice::Renderer>(
      new BoundedWavFileWriter(filename, sampling_frequency_in_hz));
}

std::unique_ptr<FakeAudioDevice::Renderer>
    FakeAudioDevice::CreateDiscardRenderer(int sampling_frequency_in_hz) {
  return std::unique_ptr<FakeAudioDevice::Renderer>(
      new DiscardRenderer(sampling_frequency_in_hz));
}


FakeAudioDevice::FakeAudioDevice(std::unique_ptr<Capturer> capturer,
                                 std::unique_ptr<Renderer> renderer,
                                 float speed)
    : capturer_(std::move(capturer)),
      renderer_(std::move(renderer)),
      speed_(speed),
      audio_callback_(nullptr),
      rendering_(false),
      capturing_(false),
      done_rendering_(true, true),
      done_capturing_(true, true),
      tick_(EventTimerWrapper::Create()),
      thread_(FakeAudioDevice::Run, this, "FakeAudioDevice") {
  auto good_sample_rate = [](int sr) {
    return sr == 8000 || sr == 16000 || sr == 32000
        || sr == 44100 || sr == 48000;
  };

  if (renderer_) {
    const int sample_rate = renderer_->SamplingFrequency();
    playout_buffer_.resize(SamplesPerFrame(sample_rate), 0);
    RTC_CHECK(good_sample_rate(sample_rate));
  }
  if (capturer_) {
    RTC_CHECK(good_sample_rate(capturer_->SamplingFrequency()));
  }
}

FakeAudioDevice::~FakeAudioDevice() {
  StopPlayout();
  StopRecording();
  thread_.Stop();
}

int32_t FakeAudioDevice::StartPlayout() {
  rtc::CritScope cs(&lock_);
  RTC_CHECK(renderer_);
  rendering_ = true;
  done_rendering_.Reset();
  return 0;
}

int32_t FakeAudioDevice::StopPlayout() {
  rtc::CritScope cs(&lock_);
  rendering_ = false;
  done_rendering_.Set();
  return 0;
}

int32_t FakeAudioDevice::StartRecording() {
  rtc::CritScope cs(&lock_);
  RTC_CHECK(capturer_);
  capturing_ = true;
  done_capturing_.Reset();
  return 0;
}

int32_t FakeAudioDevice::StopRecording() {
  rtc::CritScope cs(&lock_);
  capturing_ = false;
  done_capturing_.Set();
  return 0;
}

int32_t FakeAudioDevice::Init() {
  RTC_CHECK(tick_->StartTimer(true, kFrameLengthMs / speed_));
  thread_.Start();
  thread_.SetPriority(rtc::kHighPriority);
  return 0;
}

int32_t FakeAudioDevice::RegisterAudioCallback(AudioTransport* callback) {
  rtc::CritScope cs(&lock_);
  RTC_DCHECK(callback || audio_callback_);
  audio_callback_ = callback;
  return 0;
}

bool FakeAudioDevice::Playing() const {
  rtc::CritScope cs(&lock_);
  return rendering_;
}

bool FakeAudioDevice::Recording() const {
  rtc::CritScope cs(&lock_);
  return capturing_;
}

bool FakeAudioDevice::WaitForPlayoutEnd(int timeout_ms) {
  return done_rendering_.Wait(timeout_ms);
}

bool FakeAudioDevice::WaitForRecordingEnd(int timeout_ms) {
  return done_capturing_.Wait(timeout_ms);
}

bool FakeAudioDevice::Run(void* obj) {
  static_cast<FakeAudioDevice*>(obj)->ProcessAudio();
  return true;
}

void FakeAudioDevice::ProcessAudio() {
  {
    rtc::CritScope cs(&lock_);
    if (capturing_) {
      // Capture 10ms of audio. 2 bytes per sample.
      const bool keep_capturing = capturer_->Capture(&recording_buffer_);
      uint32_t new_mic_level;
      if (recording_buffer_.size() > 0) {
        audio_callback_->RecordedDataIsAvailable(
            recording_buffer_.data(), recording_buffer_.size(), 2, 1,
            capturer_->SamplingFrequency(), 0, 0, 0, false, new_mic_level);
      }
      if (!keep_capturing) {
        capturing_ = false;
        done_capturing_.Set();
      }
    }
    if (rendering_) {
      size_t samples_out;
      int64_t elapsed_time_ms;
      int64_t ntp_time_ms;
      const int sampling_frequency = renderer_->SamplingFrequency();
      audio_callback_->NeedMorePlayData(
          SamplesPerFrame(sampling_frequency), 2, 1, sampling_frequency,
          playout_buffer_.data(), samples_out, &elapsed_time_ms, &ntp_time_ms);
      const bool keep_rendering = renderer_->Render(
          rtc::ArrayView<const int16_t>(playout_buffer_.data(), samples_out));
      if (!keep_rendering) {
        rendering_ = false;
        done_rendering_.Set();
      }
    }
  }
  tick_->Wait(WEBRTC_EVENT_INFINITE);
}


}  // namespace test
}  // namespace webrtc
