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

#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_manager.h"
#include "rtc_base/experiments/field_trial_parser.h"

namespace webrtc {

// This is the class for the decision tree implementation.
class DecisionLogic : public NetEqController {
 public:
  static const int kReinitAfterExpands = 100;
  static const int kMaxWaitForPacket = 10;

  // Constructor.
  DecisionLogic(NetEqController::Config config);
  DecisionLogic(NetEqController::Config config,
                std::unique_ptr<DelayManager> delay_manager,
                std::unique_ptr<BufferLevelFilter> buffer_level_filter);

  ~DecisionLogic() override;

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

  // Resets object to a clean state.
  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;

  // These methods test the `cng_state_` for different conditions.
  bool CngRfc3389On() const override { return cng_state_ == kCngRfc3389On; }
  bool CngOff() const override { return cng_state_ == kCngOff; }

  // Resets the `cng_state_` to kCngOff.
  void SetCngOff() override { cng_state_ = kCngOff; }

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

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

  int TargetLevelMs() const override { return delay_manager_->TargetDelayMs(); }

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

  void RegisterEmptyPacket() override {}

  void NotifyMutedState() override;

  bool SetMaximumDelay(int delay_ms) override {
    return delay_manager_->SetMaximumDelay(delay_ms);
  }
  bool SetMinimumDelay(int delay_ms) override {
    return delay_manager_->SetMinimumDelay(delay_ms);
  }
  bool SetBaseMinimumDelay(int delay_ms) override {
    return delay_manager_->SetBaseMinimumDelay(delay_ms);
  }
  int GetBaseMinimumDelay() const override {
    return delay_manager_->GetBaseMinimumDelay();
  }
  bool PeakFound() const override { return false; }

  int GetFilteredBufferLevel() const override {
    return buffer_level_filter_->filtered_current_level();
  }

  // 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;

  enum CngState { kCngOff, kCngRfc3389On, kCngInternalOn };

  // 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(NetEq::Mode prev_mode,
                                        uint32_t target_timestamp,
                                        uint32_t available_timestamp,
                                        size_t generated_noise_samples);

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

  // Returns the operation to do given that the expected packet is available.
  virtual NetEq::Operation ExpectedPacketAvailable(NetEq::Mode prev_mode,
                                                   bool play_dtmf);

  // 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(
      size_t decoder_frame_length,
      NetEq::Mode prev_mode,
      uint32_t target_timestamp,
      uint32_t available_timestamp,
      bool play_dtmf,
      size_t generated_noise_samples,
      size_t span_samples_in_packet_buffer,
      size_t num_packets_in_packet_buffer);

  // 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 `timestamp_leap` is so long into the future that a reset due
  // to exceeding kReinitAfterExpands will be done.
  bool ReinitAfterExpands(uint32_t timestamp_leap) const;

  // Checks if we still have not done enough expands to cover the distance from
  // the last decoded packet to the next available packet, the distance beeing
  // conveyed in `timestamp_leap`.
  bool PacketTooEarly(uint32_t timestamp_leap) const;

  // Checks if num_consecutive_expands_ >= kMaxWaitForPacket.
  bool MaxWaitForPacket() const;

  std::unique_ptr<DelayManager> delay_manager_;
  std::unique_ptr<BufferLevelFilter> buffer_level_filter_;
  const TickTimer* tick_timer_;
  int sample_rate_;
  size_t output_size_samples_;
  CngState cng_state_ = kCngOff;  // Remember if comfort noise is interrupted by
                                  // other event (e.g., DTMF).
  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 num_consecutive_expands_ = 0;
  int time_stretched_cn_samples_ = 0;
  bool last_pack_cng_or_dtmf_ = true;
  bool buffer_flush_ = false;
  FieldTrialConstrained<int> target_level_window_ms_;
};

}  // namespace webrtc
#endif  // MODULES_AUDIO_CODING_NETEQ_DECISION_LOGIC_H_
