/*
 *  Copyright (c) 2020 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 "audio/voip/voip_core.h"

#include <algorithm>
#include <memory>
#include <utility>

#include "api/audio_codecs/audio_format.h"
#include "rtc_base/logging.h"

namespace webrtc {

namespace {

// For Windows, use specific enum type to initialize default audio device as
// defined in AudioDeviceModule::WindowsDeviceType.
#if defined(WEBRTC_WIN)
constexpr AudioDeviceModule::WindowsDeviceType kAudioDeviceId =
    AudioDeviceModule::WindowsDeviceType::kDefaultCommunicationDevice;
#else
constexpr uint16_t kAudioDeviceId = 0;
#endif  // defined(WEBRTC_WIN)

// Maximum value range limit on ChannelId. This can be increased without any
// side effect and only set at this moderate value for better readability for
// logging.
static constexpr int kMaxChannelId = 100000;

}  // namespace

VoipCore::VoipCore(const Environment& env,
                   rtc::scoped_refptr<AudioEncoderFactory> encoder_factory,
                   rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
                   rtc::scoped_refptr<AudioDeviceModule> audio_device_module,
                   rtc::scoped_refptr<AudioProcessing> audio_processing)
    : env_(env),
      encoder_factory_(std::move(encoder_factory)),
      decoder_factory_(std::move(decoder_factory)),
      audio_processing_(std::move(audio_processing)),
      audio_device_module_(std::move(audio_device_module)) {
  audio_mixer_ = AudioMixerImpl::Create();

  // AudioTransportImpl depends on audio mixer and audio processing instances.
  audio_transport_ = std::make_unique<AudioTransportImpl>(
      audio_mixer_.get(), audio_processing_.get(), nullptr);
}

bool VoipCore::InitializeIfNeeded() {
  // `audio_device_module_` internally owns a lock and the whole logic here
  // needs to be executed atomically once using another lock in VoipCore.
  // Further changes in this method will need to make sure that no deadlock is
  // introduced in the future.
  MutexLock lock(&lock_);

  if (initialized_) {
    return true;
  }

  // Initialize ADM.
  if (audio_device_module_->Init() != 0) {
    RTC_LOG(LS_ERROR) << "Failed to initialize the ADM.";
    return false;
  }

  // Note that failures on initializing default recording/speaker devices are
  // not considered to be fatal here. In certain case, caller may not care about
  // recording device functioning (e.g webinar where only speaker is available).
  // It's also possible that there are other audio devices available that may
  // work.

  // Initialize default speaker device.
  if (audio_device_module_->SetPlayoutDevice(kAudioDeviceId) != 0) {
    RTC_LOG(LS_WARNING) << "Unable to set playout device.";
  }
  if (audio_device_module_->InitSpeaker() != 0) {
    RTC_LOG(LS_WARNING) << "Unable to access speaker.";
  }

  // Initialize default recording device.
  if (audio_device_module_->SetRecordingDevice(kAudioDeviceId) != 0) {
    RTC_LOG(LS_WARNING) << "Unable to set recording device.";
  }
  if (audio_device_module_->InitMicrophone() != 0) {
    RTC_LOG(LS_WARNING) << "Unable to access microphone.";
  }

  // Set number of channels on speaker device.
  bool available = false;
  if (audio_device_module_->StereoPlayoutIsAvailable(&available) != 0) {
    RTC_LOG(LS_WARNING) << "Unable to query stereo playout.";
  }
  if (audio_device_module_->SetStereoPlayout(available) != 0) {
    RTC_LOG(LS_WARNING) << "Unable to set mono/stereo playout mode.";
  }

  // Set number of channels on recording device.
  available = false;
  if (audio_device_module_->StereoRecordingIsAvailable(&available) != 0) {
    RTC_LOG(LS_WARNING) << "Unable to query stereo recording.";
  }
  if (audio_device_module_->SetStereoRecording(available) != 0) {
    RTC_LOG(LS_WARNING) << "Unable to set stereo recording mode.";
  }

  if (audio_device_module_->RegisterAudioCallback(audio_transport_.get()) !=
      0) {
    RTC_LOG(LS_WARNING) << "Unable to register audio callback.";
  }

  initialized_ = true;

  return true;
}

ChannelId VoipCore::CreateChannel(Transport* transport,
                                  std::optional<uint32_t> local_ssrc) {
  ChannelId channel_id;

  // Set local ssrc to random if not set by caller.
  if (!local_ssrc) {
    Random random(rtc::TimeMicros());
    local_ssrc = random.Rand<uint32_t>();
  }

  rtc::scoped_refptr<AudioChannel> channel =
      rtc::make_ref_counted<AudioChannel>(env_, transport, local_ssrc.value(),
                                          audio_mixer_.get(), decoder_factory_);

  {
    MutexLock lock(&lock_);

    channel_id = static_cast<ChannelId>(next_channel_id_);
    channels_[channel_id] = channel;
    next_channel_id_++;
    if (next_channel_id_ >= kMaxChannelId) {
      next_channel_id_ = 0;
    }
  }

  // Set ChannelId in audio channel for logging/debugging purpose.
  channel->SetId(channel_id);

  return channel_id;
}

VoipResult VoipCore::ReleaseChannel(ChannelId channel_id) {
  // Destroy channel outside of the lock.
  rtc::scoped_refptr<AudioChannel> channel;

  bool no_channels_after_release = false;

  {
    MutexLock lock(&lock_);

    auto iter = channels_.find(channel_id);
    if (iter != channels_.end()) {
      channel = std::move(iter->second);
      channels_.erase(iter);
    }

    no_channels_after_release = channels_.empty();
  }

  VoipResult status_code = VoipResult::kOk;
  if (!channel) {
    RTC_LOG(LS_WARNING) << "Channel " << channel_id << " not found";
    status_code = VoipResult::kInvalidArgument;
  }

  if (no_channels_after_release) {
    // TODO(bugs.webrtc.org/11581): unclear if we still need to clear `channel`
    // here.
    channel = nullptr;

    // Make sure to stop playout on ADM if it is playing.
    if (audio_device_module_->Playing()) {
      if (audio_device_module_->StopPlayout() != 0) {
        RTC_LOG(LS_WARNING) << "StopPlayout failed";
        status_code = VoipResult::kInternal;
      }
    }
  }

  return status_code;
}

rtc::scoped_refptr<AudioChannel> VoipCore::GetChannel(ChannelId channel_id) {
  rtc::scoped_refptr<AudioChannel> channel;
  {
    MutexLock lock(&lock_);
    auto iter = channels_.find(channel_id);
    if (iter != channels_.end()) {
      channel = iter->second;
    }
  }
  if (!channel) {
    RTC_LOG(LS_ERROR) << "Channel " << channel_id << " not found";
  }
  return channel;
}

bool VoipCore::UpdateAudioTransportWithSenders() {
  std::vector<AudioSender*> audio_senders;

  // Gather a list of audio channel that are currently sending along with
  // highest sampling rate and channel numbers to configure into audio
  // transport.
  int max_sampling_rate = 8000;
  size_t max_num_channels = 1;
  {
    MutexLock lock(&lock_);
    // Reserve to prevent run time vector re-allocation.
    audio_senders.reserve(channels_.size());
    for (auto kv : channels_) {
      rtc::scoped_refptr<AudioChannel>& channel = kv.second;
      if (channel->IsSendingMedia()) {
        auto encoder_format = channel->GetEncoderFormat();
        if (!encoder_format) {
          RTC_LOG(LS_ERROR)
              << "channel " << channel->GetId() << " encoder is not set";
          continue;
        }
        audio_senders.push_back(channel->GetAudioSender());
        max_sampling_rate =
            std::max(max_sampling_rate, encoder_format->clockrate_hz);
        max_num_channels =
            std::max(max_num_channels, encoder_format->num_channels);
      }
    }
  }

  audio_transport_->UpdateAudioSenders(audio_senders, max_sampling_rate,
                                       max_num_channels);

  // Depending on availability of senders, turn on or off ADM recording.
  if (!audio_senders.empty()) {
    // Initialize audio device module and default device if needed.
    if (!InitializeIfNeeded()) {
      return false;
    }

    if (!audio_device_module_->Recording()) {
      if (audio_device_module_->InitRecording() != 0) {
        RTC_LOG(LS_ERROR) << "InitRecording failed";
        return false;
      }
      if (audio_device_module_->StartRecording() != 0) {
        RTC_LOG(LS_ERROR) << "StartRecording failed";
        return false;
      }
    }
  } else {
    if (audio_device_module_->Recording() &&
        audio_device_module_->StopRecording() != 0) {
      RTC_LOG(LS_ERROR) << "StopRecording failed";
      return false;
    }
  }
  return true;
}

VoipResult VoipCore::StartSend(ChannelId channel_id) {
  rtc::scoped_refptr<AudioChannel> channel = GetChannel(channel_id);

  if (!channel) {
    return VoipResult::kInvalidArgument;
  }

  if (!channel->StartSend()) {
    return VoipResult::kFailedPrecondition;
  }

  return UpdateAudioTransportWithSenders() ? VoipResult::kOk
                                           : VoipResult::kInternal;
}

VoipResult VoipCore::StopSend(ChannelId channel_id) {
  rtc::scoped_refptr<AudioChannel> channel = GetChannel(channel_id);

  if (!channel) {
    return VoipResult::kInvalidArgument;
  }

  channel->StopSend();

  return UpdateAudioTransportWithSenders() ? VoipResult::kOk
                                           : VoipResult::kInternal;
}

VoipResult VoipCore::StartPlayout(ChannelId channel_id) {
  rtc::scoped_refptr<AudioChannel> channel = GetChannel(channel_id);

  if (!channel) {
    return VoipResult::kInvalidArgument;
  }

  if (channel->IsPlaying()) {
    return VoipResult::kOk;
  }

  if (!channel->StartPlay()) {
    return VoipResult::kFailedPrecondition;
  }

  // Initialize audio device module and default device if needed.
  if (!InitializeIfNeeded()) {
    return VoipResult::kInternal;
  }

  if (!audio_device_module_->Playing()) {
    if (audio_device_module_->InitPlayout() != 0) {
      RTC_LOG(LS_ERROR) << "InitPlayout failed";
      return VoipResult::kInternal;
    }
    if (audio_device_module_->StartPlayout() != 0) {
      RTC_LOG(LS_ERROR) << "StartPlayout failed";
      return VoipResult::kInternal;
    }
  }

  return VoipResult::kOk;
}

VoipResult VoipCore::StopPlayout(ChannelId channel_id) {
  rtc::scoped_refptr<AudioChannel> channel = GetChannel(channel_id);

  if (!channel) {
    return VoipResult::kInvalidArgument;
  }

  channel->StopPlay();

  return VoipResult::kOk;
}

VoipResult VoipCore::ReceivedRTPPacket(
    ChannelId channel_id,
    rtc::ArrayView<const uint8_t> rtp_packet) {
  rtc::scoped_refptr<AudioChannel> channel = GetChannel(channel_id);

  if (!channel) {
    return VoipResult::kInvalidArgument;
  }

  channel->ReceivedRTPPacket(rtp_packet);

  return VoipResult::kOk;
}

VoipResult VoipCore::ReceivedRTCPPacket(
    ChannelId channel_id,
    rtc::ArrayView<const uint8_t> rtcp_packet) {
  rtc::scoped_refptr<AudioChannel> channel = GetChannel(channel_id);

  if (!channel) {
    return VoipResult::kInvalidArgument;
  }

  channel->ReceivedRTCPPacket(rtcp_packet);

  return VoipResult::kOk;
}

VoipResult VoipCore::SetSendCodec(ChannelId channel_id,
                                  int payload_type,
                                  const SdpAudioFormat& encoder_format) {
  rtc::scoped_refptr<AudioChannel> channel = GetChannel(channel_id);

  if (!channel) {
    return VoipResult::kInvalidArgument;
  }

  auto encoder = encoder_factory_->Create(env_, encoder_format,
                                          {.payload_type = payload_type});
  channel->SetEncoder(payload_type, encoder_format, std::move(encoder));

  return VoipResult::kOk;
}

VoipResult VoipCore::SetReceiveCodecs(
    ChannelId channel_id,
    const std::map<int, SdpAudioFormat>& decoder_specs) {
  rtc::scoped_refptr<AudioChannel> channel = GetChannel(channel_id);

  if (!channel) {
    return VoipResult::kInvalidArgument;
  }

  channel->SetReceiveCodecs(decoder_specs);

  return VoipResult::kOk;
}

VoipResult VoipCore::RegisterTelephoneEventType(ChannelId channel_id,
                                                int rtp_payload_type,
                                                int sample_rate_hz) {
  rtc::scoped_refptr<AudioChannel> channel = GetChannel(channel_id);

  if (!channel) {
    return VoipResult::kInvalidArgument;
  }

  channel->RegisterTelephoneEventType(rtp_payload_type, sample_rate_hz);

  return VoipResult::kOk;
}

VoipResult VoipCore::SendDtmfEvent(ChannelId channel_id,
                                   DtmfEvent dtmf_event,
                                   int duration_ms) {
  rtc::scoped_refptr<AudioChannel> channel = GetChannel(channel_id);

  if (!channel) {
    return VoipResult::kInvalidArgument;
  }

  return (channel->SendTelephoneEvent(static_cast<int>(dtmf_event), duration_ms)
              ? VoipResult::kOk
              : VoipResult::kFailedPrecondition);
}

VoipResult VoipCore::GetIngressStatistics(ChannelId channel_id,
                                          IngressStatistics& ingress_stats) {
  rtc::scoped_refptr<AudioChannel> channel = GetChannel(channel_id);

  if (!channel) {
    return VoipResult::kInvalidArgument;
  }

  ingress_stats = channel->GetIngressStatistics();

  return VoipResult::kOk;
}

VoipResult VoipCore::GetChannelStatistics(ChannelId channel_id,
                                          ChannelStatistics& channel_stats) {
  rtc::scoped_refptr<AudioChannel> channel = GetChannel(channel_id);

  if (!channel) {
    return VoipResult::kInvalidArgument;
  }

  channel_stats = channel->GetChannelStatistics();

  return VoipResult::kOk;
}

VoipResult VoipCore::SetInputMuted(ChannelId channel_id, bool enable) {
  rtc::scoped_refptr<AudioChannel> channel = GetChannel(channel_id);

  if (!channel) {
    return VoipResult::kInvalidArgument;
  }

  channel->SetMute(enable);

  return VoipResult::kOk;
}

VoipResult VoipCore::GetInputVolumeInfo(ChannelId channel_id,
                                        VolumeInfo& input_volume) {
  rtc::scoped_refptr<AudioChannel> channel = GetChannel(channel_id);

  if (!channel) {
    return VoipResult::kInvalidArgument;
  }

  input_volume.audio_level = channel->GetInputAudioLevel();
  input_volume.total_energy = channel->GetInputTotalEnergy();
  input_volume.total_duration = channel->GetInputTotalDuration();

  return VoipResult::kOk;
}

VoipResult VoipCore::GetOutputVolumeInfo(ChannelId channel_id,
                                         VolumeInfo& output_volume) {
  rtc::scoped_refptr<AudioChannel> channel = GetChannel(channel_id);

  if (!channel) {
    return VoipResult::kInvalidArgument;
  }

  output_volume.audio_level = channel->GetOutputAudioLevel();
  output_volume.total_energy = channel->GetOutputTotalEnergy();
  output_volume.total_duration = channel->GetOutputTotalDuration();

  return VoipResult::kOk;
}

}  // namespace webrtc
