/*
 *  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,
                                  absl::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
