// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <fuchsia/media/cpp/fidl.h>
#include <zircon/device/audio.h>

#include <cmath>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "src/lib/files/path.h"
#include "src/media/audio/audio_core/testing/integration/hermetic_audio_realm.h"
#include "src/media/audio/audio_core/testing/integration/hermetic_audio_test.h"
#include "src/media/audio/audio_core/testing/integration/virtual_device.h"
#include "src/media/audio/lib/format/audio_buffer.h"
#include "src/media/audio/lib/format/format.h"
#include "src/media/audio/lib/format/traits.h"
#include "src/virtualization/tests/enclosed_guest.h"

namespace {

using ::fuchsia::media::AudioSampleFormat;
using ::media::audio::AudioBuffer;
using ::media::audio::AudioBufferSlice;
using ::media::audio::Format;
using ::media::audio::SampleFormatTraits;
using ::media::audio::test::HermeticAudioRealm;
using ::media::audio::test::HermeticAudioTest;
using ::media::audio::test::VirtualOutput;

constexpr int32_t kOutputFrameRate = 48000;
constexpr int32_t kStereoChannelCount = 2;
constexpr AudioSampleFormat kSampleFormat = AudioSampleFormat::FLOAT;

constexpr audio_stream_unique_id_t kOutputId = AUDIO_STREAM_UNIQUE_ID_BUILTIN_SPEAKERS;

// TODO(fxbug.dev/87646): Consider creating a `virtio_audio_test_util` that directly communicates
// with ALSA instead to have better control over the output buffer.
constexpr char kAplayBinPath[] = "/tmp/vm_extras/aplay";

// TODO(fxbug.dev/87646): Consider creating a `virtio_audio_test_util` that directly generates this
// audio files on-the-fly.
constexpr char kTestFilePath[] = "/tmp/extras/stereo_ramp_48khz_16bit.wav";

constexpr int32_t kRampFrameCount = 65536;
constexpr int32_t kZeroPaddingFrameCount = 1024;

template <class GuestType>
class VirtioSoundGuestTest : public HermeticAudioTest {
 protected:
  void SetUp() override {
    GuestLaunchInfo guest_launch_info;
    enclosed_guest_.emplace(loop());

    HermeticAudioTest::SetTestSuiteRealmOptions([this, &guest_launch_info] {
      return HermeticAudioRealm::Options{
          .customize_realm = [this, &guest_launch_info](
                                 ::component_testing::RealmBuilder& realm_builder) -> zx_status_t {
            auto status = enclosed_guest_->InstallInRealm(realm_builder, guest_launch_info);
            if (status != ZX_OK) {
              return status;
            }

            using component_testing::ChildRef;
            using component_testing::Protocol;
            using component_testing::Route;

            realm_builder.AddRoute(Route{
                .capabilities = {Protocol{"fuchsia.media.Audio"}},
                .source = ChildRef{HermeticAudioRealm::kAudioCore},
                .targets = {ChildRef{"guest_manager"}},
            });
            return ZX_OK;
          },
      };
    });

    // Create the realm and start audio services.
    HermeticAudioTest::SetUp();

    // Now start the guest.
    ASSERT_EQ(enclosed_guest_->LaunchInRealm(realm().realm_root(), guest_launch_info,
                                             zx::time::infinite()),
              ZX_OK)
        << "Failed to launch guest";

    const auto format =
        Format::Create<kSampleFormat>(kStereoChannelCount, kOutputFrameRate).take_value();
    // Add some padding to ensure that there is enough headroom in the ring buffer.
    output_ = CreateOutput(kOutputId, format,
                           kRampFrameCount + kZeroPaddingFrameCount + 10 * kOutputFrameRate);
  }

  void TearDown() override {
    EXPECT_EQ(enclosed_guest_->Stop(zx::time::infinite()), ZX_OK);
    enclosed_guest_.reset();

    if constexpr (kEnableAllOverflowAndUnderflowChecksInRealtimeTests) {
      ExpectNoOverflowsOrUnderflows();
    }
    HermeticAudioTest::TearDown();
  }

  zx_status_t Execute(const std::vector<std::string>& argv) {
    return enclosed_guest_->Execute(argv, {}, zx::time::infinite(), nullptr, nullptr);
  }

  std::optional<int64_t> GetFirstNonSilentFrame(const AudioBuffer<kSampleFormat>& buffer) const {
    for (int64_t frame = 0; frame < buffer.NumFrames(); ++frame) {
      if (buffer.SampleAt(frame, 0) != SampleFormatTraits<kSampleFormat>::kSilentValue) {
        return frame;
      }
    }
    return std::nullopt;
  }

  AudioBuffer<kSampleFormat> GetOutputRingBuffer() { return output_->SnapshotRingBuffer(); }

  bool OutputHasUnderflows() { return DeviceHasUnderflows(output_); }

 private:
  std::optional<GuestType> enclosed_guest_;
  VirtualOutput<kSampleFormat>* output_ = nullptr;
};

// We only support `TerminaEnclosedGuest` since the tests require `virtio-sound` and `alsa-lib`.
TYPED_TEST_SUITE(VirtioSoundGuestTest, ::testing::Types<TerminaEnclosedGuest>,
                 GuestTestNameGenerator);

TYPED_TEST(VirtioSoundGuestTest, OutputFidelity) {
  // The input audio file consists of a stereo linear ramp that covers the entire 16-bit range of
  // values with opposing direction in each channel. It is calculated for each frame as follows:
  //    `buffer[frame][0] = 0x7FFF - frame`
  //    `buffer[frame][1] = -0x8000 + frame`
  // Note that the file consists of `kZeroPaddingFrameCount` frames of zeros at the beginning in
  // order to compensate for the initial gain ramp, which is then followed by the
  // `kRampFrameCount` ramp frames as described above.
  ASSERT_EQ(this->Execute({kAplayBinPath, kTestFilePath}), ZX_OK);

  const auto ring_buffer = this->GetOutputRingBuffer();
  ASSERT_EQ(ring_buffer.format().channels(), kStereoChannelCount);

  // TODO(fxbug.dev/80003): Remove workarounds when underflow conditions are fixed.
  if (this->OutputHasUnderflows()) {
    GTEST_SKIP() << "Skipping fidelity checks due to underflows";
    __builtin_unreachable();
  }

  const std::optional<int64_t> start_frame = this->GetFirstNonSilentFrame(ring_buffer);
  ASSERT_TRUE(start_frame.has_value()) << "Could not find non-silent frame";
  FX_LOGS(INFO) << "First non-silent frame: " << *start_frame;

  const int64_t end_frame = *start_frame + kRampFrameCount;
  ASSERT_LE(end_frame, ring_buffer.NumFrames()) << "Not enough frames in ring buffer";

  const auto buffer_slice = AudioBufferSlice(&ring_buffer, *start_frame, end_frame);
  // TODO(fxbug.dev/95106): Temporarily limit the end frame to `24000 - kZeroPaddingFrameCount`
  // until the buffer repetition issue is resolved (to be replaced by `kRampFrameCount`).
  for (int32_t frame = 0; frame < 24000 - kZeroPaddingFrameCount; ++frame) {
    EXPECT_FLOAT_EQ(buffer_slice.SampleAt(frame, 0),
                    static_cast<float>(0x7FFF - frame) / static_cast<float>(kRampFrameCount / 2))
        << "at (" << frame << ", 0)";
    EXPECT_FLOAT_EQ(buffer_slice.SampleAt(frame, 1),
                    static_cast<float>(-0x8000 + frame) / static_cast<float>(kRampFrameCount / 2))
        << "at (" << frame << ", 1)";
  }
}

}  // namespace
