// Copyright 2019 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 "src/media/audio/audio_core/effects_stage.h"

#include "src/media/audio/lib/effects_loader/effects_loader.h"
#include "src/media/audio/lib/effects_loader/effects_processor.h"

namespace media::audio {
namespace {

class MultiLibEffectsLoader {
 public:
  Effect CreateEffectByName(std::string_view lib_name, std::string_view effect_name,
                            std::string_view instance_name, uint32_t frame_rate,
                            uint16_t channels_in, uint16_t channels_out, std::string_view config) {
    auto it = std::find_if(holders_.begin(), holders_.end(),
                           [lib_name](auto& holder) { return holder.lib_name == lib_name; });
    if (it == holders_.end()) {
      Holder holder;
      holder.lib_name = lib_name;
      zx_status_t status = EffectsLoader::CreateWithModule(holder.lib_name.c_str(), &holder.loader);
      if (status != ZX_OK) {
        return {};
      }
      it = holders_.insert(it, std::move(holder));
    }

    FX_CHECK(it != holders_.end());
    return it->loader->CreateEffectByName(effect_name, instance_name, frame_rate, channels_in,
                                          channels_out, config);
  }

 private:
  struct Holder {
    std::string lib_name;
    std::unique_ptr<EffectsLoader> loader;
  };
  std::vector<Holder> holders_;
};

std::pair<int64_t, uint32_t> AlignBufferRequest(int64_t frame, uint32_t length,
                                                uint32_t alignment) {
  uint64_t mask = ~(static_cast<uint64_t>(alignment) - 1);
  int64_t aligned_frame = frame & mask;
  uint32_t aligned_length = (length + alignment - 1) & mask;
  return {aligned_frame, aligned_length};
}

}  // namespace

// static
std::shared_ptr<EffectsStage> EffectsStage::Create(
    const std::vector<PipelineConfig::Effect>& effects, std::shared_ptr<Stream> source) {
  TRACE_DURATION("audio", "EffectsStage::Create");
  if (source->format().sample_format() != fuchsia::media::AudioSampleFormat::FLOAT) {
    FX_LOGS(ERROR) << "EffectsStage can only be added to streams with FLOAT samples";
    return nullptr;
  }

  auto processor = std::make_unique<EffectsProcessor>();

  MultiLibEffectsLoader loader;
  uint32_t frame_rate = source->format().frames_per_second();
  uint16_t channels = source->format().channels();
  for (const auto& effect_spec : effects) {
    auto effect = loader.CreateEffectByName(effect_spec.lib_name, effect_spec.effect_name,
                                            effect_spec.instance_name, frame_rate, channels,
                                            channels, effect_spec.effect_config);
    FX_DCHECK(effect);
    if (!effect) {
      FX_LOGS(ERROR) << "Unable to create effect '" << effect_spec.effect_name << "' with config '"
                     << effect_spec.effect_config << "' from lib '" << effect_spec.lib_name << "'";
      continue;
    }
    processor->AddEffect(std::move(effect));
  }

  return std::make_shared<EffectsStage>(std::move(source), std::move(processor));
}

std::optional<Stream::Buffer> EffectsStage::LockBuffer(zx::time ref_time, int64_t frame,
                                                       uint32_t frame_count) {
  TRACE_DURATION("audio", "EffectsStage::LockBuffer", "frame", frame, "length", frame_count);
  // If we have a partially consumed block, return that here.
  if (current_block_ && frame >= current_block_->start() && frame < current_block_->end()) {
    return current_block_;
  }

  // New frames are requested. Block-align the start frame and length.
  auto [aligned_first_frame, aligned_frame_count] =
      AlignBufferRequest(frame, frame_count, effects_processor_->block_size());

  // Ensure we don't try to push more frames through our effects processor than supported.
  uint32_t max_batch_size = effects_processor_->max_batch_size();
  if (max_batch_size) {
    aligned_frame_count = std::min<uint32_t>(aligned_frame_count, max_batch_size);
  }

  current_block_ = source_->LockBuffer(ref_time, aligned_first_frame, aligned_frame_count);
  if (current_block_) {
    FX_DCHECK(current_block_->start().Floor() == aligned_first_frame);
    FX_DCHECK(current_block_->length().Floor() == aligned_frame_count);

    auto payload = static_cast<float*>(current_block_->payload());
    effects_processor_->ProcessInPlace(aligned_frame_count, payload);
  }
  return current_block_;
}

Stream::TimelineFunctionSnapshot EffectsStage::ReferenceClockToFractionalFrames() const {
  auto snapshot = source_->ReferenceClockToFractionalFrames();

  // Update our timeline function to include the latency introduced by these effects.
  //
  // Our effects shift incoming audio into the future by "delay_frames".
  // So input frame[N] corresponds to output frame[N + delay_frames].
  int64_t delay_frames = effects_processor_->delay_frames();
  auto delay_frac_frames = FractionalFrames<int64_t>(delay_frames);

  auto source_frac_frame_to_dest_frac_frame =
      TimelineFunction(delay_frac_frames.raw_value(), 0, TimelineRate(1, 1));
  snapshot.timeline_function = source_frac_frame_to_dest_frac_frame * snapshot.timeline_function;

  return snapshot;
}

void EffectsStage::SetEffectConfig(const std::string& instance_name, const std::string& config) {
  for (auto& effect : *effects_processor_) {
    if (effect.instance_name() == instance_name) {
      effect.UpdateConfiguration(config);
    }
  }
}

}  // namespace media::audio
