/*
 *  Copyright 2015 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 "webrtc/api/mediacontroller.h"

#include <memory>

#include "webrtc/base/bind.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/constructormagic.h"
#include "webrtc/call.h"
#include "webrtc/pc/channelmanager.h"
#include "webrtc/media/base/mediachannel.h"

namespace {

const int kMinBandwidthBps = 30000;
const int kStartBandwidthBps = 300000;
const int kMaxBandwidthBps = 2000000;

class MediaController : public webrtc::MediaControllerInterface,
                        public sigslot::has_slots<> {
 public:
  MediaController(const cricket::MediaConfig& media_config,
                  rtc::Thread* worker_thread,
                  cricket::ChannelManager* channel_manager)
      : worker_thread_(worker_thread),
        media_config_(media_config),
        channel_manager_(channel_manager) {
    RTC_DCHECK(worker_thread);
    worker_thread_->Invoke<void>(RTC_FROM_HERE,
                                 rtc::Bind(&MediaController::Construct_w, this,
                                           channel_manager_->media_engine()));
  }
  ~MediaController() override {
    Close();
  }

  // webrtc::MediaControllerInterface implementation.
  void Close() override {
    worker_thread_->Invoke<void>(RTC_FROM_HERE,
                                 rtc::Bind(&MediaController::Close_w, this));
  }
  webrtc::Call* call_w() override {
    RTC_DCHECK(worker_thread_->IsCurrent());
    if (!call_) {
      call_.reset(webrtc::Call::Create(call_config_));
    }
    return call_.get();
  }
  cricket::ChannelManager* channel_manager() const override {
    return channel_manager_;
  }
  const cricket::MediaConfig& config() const override { return media_config_; }

 private:
  void Construct_w(cricket::MediaEngineInterface* media_engine) {
    RTC_DCHECK(worker_thread_->IsCurrent());
    RTC_DCHECK(media_engine);
    call_config_.audio_state = media_engine->GetAudioState();
    call_config_.bitrate_config.min_bitrate_bps = kMinBandwidthBps;
    call_config_.bitrate_config.start_bitrate_bps = kStartBandwidthBps;
    call_config_.bitrate_config.max_bitrate_bps = kMaxBandwidthBps;
  }
  void Close_w() {
    RTC_DCHECK(worker_thread_->IsCurrent());
    call_.reset();
  }

  rtc::Thread* const worker_thread_;
  const cricket::MediaConfig media_config_;
  cricket::ChannelManager* const channel_manager_;
  webrtc::Call::Config call_config_;
  std::unique_ptr<webrtc::Call> call_;

  RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(MediaController);
};
}  // namespace {

namespace webrtc {

MediaControllerInterface* MediaControllerInterface::Create(
    const cricket::MediaConfig& config,
    rtc::Thread* worker_thread,
    cricket::ChannelManager* channel_manager) {
  return new MediaController(config, worker_thread, channel_manager);
}
}  // namespace webrtc
