/*
 *  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.
 */

#ifndef MODULES_AUDIO_CODING_NETEQ_DECISION_LOGIC_H_
#define MODULES_AUDIO_CODING_NETEQ_DECISION_LOGIC_H_

#include <cstddef>
#include <cstdint>
#include <memory>
#include <optional>

#include "api/environment/environment.h"
#include "api/neteq/delay_manager_interface.h"
#include "api/neteq/neteq.h"
#include "api/neteq/neteq_controller.h"
#include "api/neteq/tick_timer.h"
#include "modules/audio_coding/neteq/buffer_level_filter.h"
#include "modules/audio_coding/neteq/delay_constraints.h"
#include "modules/audio_coding/neteq/packet_arrival_history.h"

namespace webrtc {

// This is the class for the decision tree implementation.
class DecisionLogic : public NetEqController {
 public:
  DecisionLogic(const Environment& env,
                NetEqController::Config config,
                std::unique_ptr<DelayManagerInterface> delay_manager);
  DecisionLogic(
      NetEqController::Config config,
      std::unique_ptr<DelayManagerInterface> delay_manager,
      std::unique_ptr<BufferLevelFilter> buffer_level_filter,
      std::unique_ptr<PacketArrivalHistory> packet_arrival_history = nullptr);

  ~DecisionLogic() override;

  DecisionLogic(const DecisionLogic&) = delete;
  DecisionLogic& operator=(const DecisionLogic&) = delete;

  // Not used.
  void Reset() override {}

  // Resets parts of the state. Typically done when switching codecs.
  void SoftReset() override;

  // Sets the sample rate and the output block size.
  void SetSampleRate(int fs_hz, size_t output_size_samples) override;

  // Given info about the latest received packet, and current jitter buffer
  // status, returns the operation. `target_timestamp` and `expand_mutefactor`
  // are provided for reference. `last_packet_samples` is the number of samples
  // obtained from the last decoded frame. If there is a packet available, it
  // should be supplied in `packet`; otherwise it should be NULL. The mode
  // resulting from the last call to NetEqImpl::GetAudio is supplied in
  // `last_mode`. If there is a DTMF event to play, `play_dtmf` should be set to
  // true. The output variable `reset_decoder` will be set to true if a reset is
  // required; otherwise it is left unchanged (i.e., it can remain true if it
  // was true before the call).
  NetEq::Operation GetDecision(const NetEqController::NetEqStatus& status,
                               bool* reset_decoder) override;

  void ExpandDecision(NetEq::Operation /* operation */) override {}

  // Adds `value` to `sample_memory_`.
  void AddSampleMemory(int32_t value) override { sample_memory_ += value; }

  int TargetLevelMs() const override;

  int UnlimitedTargetLevelMs() const override;

  std::optional<int> PacketArrived(int fs_hz,
                                   bool should_update_stats,
                                   const PacketArrivedInfo& info) override;

  void RegisterEmptyPacket() override {}

  bool SetMaximumDelay(int delay_ms) override {
    return delay_constraints_.SetMaximumDelay(delay_ms);
  }
  bool SetMinimumDelay(int delay_ms) override {
    return delay_constraints_.SetMinimumDelay(delay_ms);
  }
  bool SetBaseMinimumDelay(int delay_ms) override {
    return delay_constraints_.SetBaseMinimumDelay(delay_ms);
  }
  int GetBaseMinimumDelay() const override {
    return delay_constraints_.GetBaseMinimumDelay();
  }
  bool PeakFound() const override { return false; }

  int GetFilteredBufferLevel() const override;

  // Accessors and mutators.
  void set_sample_memory(int32_t value) override { sample_memory_ = value; }
  size_t noise_fast_forward() const override { return noise_fast_forward_; }
  size_t packet_length_samples() const override {
    return packet_length_samples_;
  }
  void set_packet_length_samples(size_t value) override {
    packet_length_samples_ = value;
  }
  void set_prev_time_scale(bool value) override { prev_time_scale_ = value; }

 private:
  // The value 5 sets maximum time-stretch rate to about 100 ms/s.
  static const int kMinTimescaleInterval = 5;

  // Updates the `buffer_level_filter_` with the current buffer level
  // `buffer_size_samples`.
  void FilterBufferLevel(size_t buffer_size_samples);

  // Returns the operation given that the next available packet is a comfort
  // noise payload (RFC 3389 only, not codec-internal).
  virtual NetEq::Operation CngOperation(NetEqController::NetEqStatus status);

  // Returns the operation given that no packets are available (except maybe
  // a DTMF event, flagged by setting `play_dtmf` true).
  virtual NetEq::Operation NoPacket(NetEqController::NetEqStatus status);

  // Returns the operation to do given that the expected packet is available.
  virtual NetEq::Operation ExpectedPacketAvailable(
      NetEqController::NetEqStatus status);

  // Returns the operation to do given that the expected packet is not
  // available, but a packet further into the future is at hand.
  virtual NetEq::Operation FuturePacketAvailable(
      NetEqController::NetEqStatus status);

  // Checks if enough time has elapsed since the last successful timescale
  // operation was done (i.e., accelerate or preemptive expand).
  bool TimescaleAllowed() const {
    return !timescale_countdown_ || timescale_countdown_->Finished();
  }

  // Checks if the current (filtered) buffer level is under the target level.
  bool UnderTargetLevel() const;

  // Checks if an ongoing concealment should be continued due to low buffer
  // level, even though the next packet is available.
  bool PostponeDecode(NetEqController::NetEqStatus status) const;

  // Checks if we still have not done enough expands to cover the distance from
  // the last decoded packet to the next available packet.
  bool PacketTooEarly(NetEqController::NetEqStatus status) const;

  int GetPlayoutDelayMs(NetEqController::NetEqStatus status) const;

  std::unique_ptr<DelayManagerInterface> delay_manager_;
  DelayConstraints delay_constraints_;
  std::unique_ptr<BufferLevelFilter> buffer_level_filter_;
  std::unique_ptr<PacketArrivalHistory> packet_arrival_history_;
  const TickTimer* tick_timer_;
  int sample_rate_khz_;
  size_t output_size_samples_;
  size_t noise_fast_forward_ = 0;
  size_t packet_length_samples_ = 0;
  int sample_memory_ = 0;
  bool prev_time_scale_ = false;
  bool disallow_time_stretching_;
  std::unique_ptr<TickTimer::Countdown> timescale_countdown_;
  int time_stretched_cn_samples_ = 0;
  bool buffer_flush_ = false;
};

}  // namespace webrtc
#endif  // MODULES_AUDIO_CODING_NETEQ_DECISION_LOGIC_H_
