/*
 * libjingle
 * Copyright 2004 Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "webrtc/libjingle/session/media/call.h"

#include <string>

#include "talk/media/base/constants.h"
#include "talk/media/base/screencastid.h"
#include "talk/session/media/currentspeakermonitor.h"
#include "webrtc/base/helpers.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/thread.h"
#include "webrtc/base/window.h"
#include "webrtc/libjingle/session/media/mediasessionclient.h"
#include "webrtc/libjingle/session/parsing.h"

namespace cricket {

const uint32 MSG_CHECKAUTODESTROY = 1;
const uint32 MSG_TERMINATECALL = 2;
const uint32 MSG_PLAYDTMF = 3;

namespace {
const int kDTMFDelay = 300;  // msec
const size_t kMaxDTMFDigits = 30;
const int kSendToVoicemailTimeout = 1000*20;
const int kNoVoicemailTimeout = 1000*180;
const int kMediaMonitorInterval = 1000*15;
// In order to be the same as the server-side switching, this must be 100.
const int kAudioMonitorPollPeriodMillis = 100;

// V is a pointer type.
template<class K, class V>
V FindOrNull(const std::map<K, V>& map,
             const K& key) {
  typename std::map<K, V>::const_iterator it = map.find(key);
  return (it != map.end()) ? it->second : NULL;
}


bool ContentContainsCrypto(const cricket::ContentInfo* content) {
  if (content != NULL) {
    const cricket::MediaContentDescription* desc =
        static_cast<const cricket::MediaContentDescription*>(
            content->description);
    if (!desc || desc->cryptos().empty()) {
      return false;
    }
  }
  return true;
}

}

AudioSourceProxy::AudioSourceProxy(Call* call)
    : call_(call) {
  call_->SignalAudioMonitor.connect(this, &AudioSourceProxy::OnAudioMonitor);
  call_->SignalMediaStreamsUpdate.connect(
      this, &AudioSourceProxy::OnMediaStreamsUpdate);
}

void AudioSourceProxy::OnAudioMonitor(Call* call, const AudioInfo& info) {
  SignalAudioMonitor(this, info);
}

void AudioSourceProxy::OnMediaStreamsUpdate(Call* call, Session* session,
    const MediaStreams& added, const MediaStreams& removed) {
  SignalMediaStreamsUpdate(this, session, added, removed);
}

Call::Call(MediaSessionClient* session_client)
    : id_(rtc::CreateRandomId()),
      session_client_(session_client),
      has_video_(false),
      has_data_(false),
      muted_(false),
      video_muted_(false),
      send_to_voicemail_(true),
      playing_dtmf_(false) {
  audio_source_proxy_.reset(new AudioSourceProxy(this));
}

Call::~Call() {
  while (media_session_map_.begin() != media_session_map_.end()) {
    Session* session = media_session_map_.begin()->second.session;
    RemoveSession(session);
    session_client_->session_manager()->DestroySession(session);
  }
  rtc::Thread::Current()->Clear(this);
}

Session* Call::InitiateSession(const buzz::Jid& to,
                               const buzz::Jid& initiator,
                               const CallOptions& options) {
  std::string id;
  std::string initiator_name = initiator.Str();
  return InternalInitiateSession(id, to, initiator_name, options);
}

Session *Call::InitiateSession(const std::string& id,
                               const buzz::Jid& to,
                               const CallOptions& options) {
  std::string initiator_name;
  return InternalInitiateSession(id, to, initiator_name, options);
}

void Call::IncomingSession(Session* session, const SessionDescription* offer) {
  AddSession(session, offer);

  // Make sure the session knows about the incoming ssrcs. This needs to be done
  // prior to the SignalSessionState call, because that may trigger handling of
  // these new SSRCs, so they need to be registered before then.
  UpdateRemoteMediaStreams(session, offer->contents(), false);

  // Missed the first state, the initiate, which is needed by
  // call_client.
  SignalSessionState(this, session, Session::STATE_RECEIVEDINITIATE);
}

void Call::AcceptSession(Session* session,
                         const cricket::CallOptions& options) {
  MediaSessionMap::iterator it = media_session_map_.find(session->id());
  if (it != media_session_map_.end()) {
    const SessionDescription* answer = session_client_->CreateAnswer(
        session->remote_description(), options);
    it->second.session->Accept(answer);
  }
}

void Call::RejectSession(Session* session) {
  // Assume polite decline.
  MediaSessionMap::iterator it = media_session_map_.find(session->id());
  if (it != media_session_map_.end())
    it->second.session->Reject(STR_TERMINATE_DECLINE);
}

void Call::TerminateSession(Session* session) {
  MediaSessionMap::iterator it = media_session_map_.find(session->id());
  if (it != media_session_map_.end()) {
    // Assume polite terminations.
    it->second.session->Terminate();
  }
}

void Call::Terminate() {
  // Copy the list so that we can iterate over it in a stable way
  std::vector<Session*> sessions = this->sessions();

  // There may be more than one session to terminate
  std::vector<Session*>::iterator it;
  for (it = sessions.begin(); it != sessions.end(); ++it) {
    TerminateSession(*it);
  }
}

bool Call::SendViewRequest(Session* session,
                           const ViewRequest& view_request) {
  StaticVideoViews::const_iterator it;
  for (it = view_request.static_video_views.begin();
       it != view_request.static_video_views.end(); ++it) {
    bool found = false;
    MediaStreams* recv_streams = GetMediaStreams(session);
    if (recv_streams)
      found = recv_streams->GetVideoStream(it->selector, nullptr);
    if (!found) {
      LOG(LS_WARNING) << "Trying to send view request for ("
                      << it->selector.ssrc << ", '"
                      << it->selector.groupid << "', '"
                      << it->selector.streamid << "'"
                      << ") is not in the local streams.";
      return false;
    }
  }

  XmlElements elems;
  WriteError error;
  if (!WriteJingleViewRequest(CN_VIDEO, view_request, &elems, &error)) {
    LOG(LS_ERROR) << "Couldn't write out view request: " << error.text;
    return false;
  }

  return session->SendInfoMessage(elems, session->remote_name());
}

void Call::SetVideoRenderer(Session* session, uint32 ssrc,
                            VideoRenderer* renderer) {
  VideoChannel* video_channel = GetVideoChannel(session);
  if (video_channel) {
    video_channel->SetRenderer(ssrc, renderer);
    LOG(LS_INFO) << "Set renderer of ssrc " << ssrc
                 << " to " << renderer << ".";
  } else {
    LOG(LS_INFO) << "Failed to set renderer of ssrc " << ssrc << ".";
  }
}

void Call::OnMessage(rtc::Message* message) {
  switch (message->message_id) {
  case MSG_CHECKAUTODESTROY:
    // If no more sessions for this call, delete it
    if (media_session_map_.empty())
      session_client_->DestroyCall(this);
    break;
  case MSG_TERMINATECALL:
    // Signal to the user that a timeout has happened and the call should
    // be sent to voicemail.
    if (send_to_voicemail_) {
      SignalSetupToCallVoicemail();
    }

    // Callee didn't answer - terminate call
    Terminate();
    break;
  case MSG_PLAYDTMF:
    ContinuePlayDTMF();
  }
}

std::vector<Session*> Call::sessions() {
  std::vector<Session*> sessions;
  MediaSessionMap::iterator it;
  for (it = media_session_map_.begin(); it != media_session_map_.end(); ++it)
    sessions.push_back(it->second.session);

  return sessions;
}

bool Call::AddSession(Session* session, const SessionDescription* offer) {
  bool succeeded = true;
  MediaSession media_session;
  media_session.session = session;
  media_session.voice_channel = NULL;
  media_session.video_channel = NULL;
  media_session.data_channel = NULL;
  media_session.recv_streams = NULL;

  const ContentInfo* audio_offer = GetFirstAudioContent(offer);
  const ContentInfo* video_offer = GetFirstVideoContent(offer);
  const ContentInfo* data_offer = GetFirstDataContent(offer);
  has_video_ = (video_offer != NULL);
  has_data_ = (data_offer != NULL);

  ASSERT(audio_offer != NULL);
  // Create voice channel and start a media monitor.
  media_session.voice_channel =
      session_client_->channel_manager()->CreateVoiceChannel(
          session, audio_offer->name, has_video_);
  // voice_channel can be NULL in case of NullVoiceEngine.
  if (media_session.voice_channel) {
    media_session.voice_channel->SignalMediaMonitor.connect(
        this, &Call::OnMediaMonitor);
    media_session.voice_channel->StartMediaMonitor(kMediaMonitorInterval);
  } else {
    succeeded = false;
  }

  // If desired, create video channel and start a media monitor.
  if (has_video_ && succeeded) {
    media_session.video_channel =
        session_client_->channel_manager()->CreateVideoChannel(
            session,
            video_offer->name,
            true,
            VideoOptions(),
            media_session.voice_channel);
    // video_channel can be NULL in case of NullVideoEngine.
    if (media_session.video_channel) {
      media_session.video_channel->SignalMediaMonitor.connect(
          this, &Call::OnMediaMonitor);
      media_session.video_channel->StartMediaMonitor(kMediaMonitorInterval);
    } else {
      succeeded = false;
    }
  }

  // If desired, create data channel.
  if (has_data_ && succeeded) {
    const DataContentDescription* data = GetFirstDataContentDescription(offer);
    if (data == NULL) {
      succeeded = false;
    } else {
      DataChannelType data_channel_type = DCT_RTP;
      if ((data->protocol() == kMediaProtocolSctp) ||
          (data->protocol() == kMediaProtocolDtlsSctp)) {
        data_channel_type = DCT_SCTP;
      }

      bool rtcp = false;
      media_session.data_channel =
          session_client_->channel_manager()->CreateDataChannel(
              session, data_offer->name, rtcp, data_channel_type);
      if (media_session.data_channel) {
        media_session.data_channel->SignalDataReceived.connect(
            this, &Call::OnDataReceived);
      } else {
        succeeded = false;
      }
    }
  }

  if (succeeded) {
    // Add session to list, create channels for this session.
    media_session.recv_streams = new MediaStreams;
    media_session_map_[session->id()] = media_session;
    session->SignalState.connect(this, &Call::OnSessionState);
    session->SignalError.connect(this, &Call::OnSessionError);
    session->SignalInfoMessage.connect(
        this, &Call::OnSessionInfoMessage);
    session->SignalRemoteDescriptionUpdate.connect(
        this, &Call::OnRemoteDescriptionUpdate);
    session->SignalReceivedTerminateReason
      .connect(this, &Call::OnReceivedTerminateReason);

    // If this call has the focus, enable this session's channels.
    if (session_client_->GetFocus() == this) {
      EnableSessionChannels(session, true);
    }

    // Signal client.
    SignalAddSession(this, session);
  }

  return succeeded;
}

void Call::RemoveSession(Session* session) {
  MediaSessionMap::iterator it = media_session_map_.find(session->id());
  if (it == media_session_map_.end())
    return;

  // Remove all the screencasts, if they haven't been already.
  while (!it->second.started_screencasts.empty()) {
    uint32 ssrc = it->second.started_screencasts.begin()->first;
    if (!StopScreencastWithoutSendingUpdate(it->second.session, ssrc)) {
      LOG(LS_ERROR) << "Unable to stop screencast with ssrc " << ssrc;
      ASSERT(false);
    }
  }

  // Destroy video channel
  VideoChannel* video_channel = it->second.video_channel;
  if (video_channel != NULL)
    session_client_->channel_manager()->DestroyVideoChannel(video_channel);

  // Destroy voice channel
  VoiceChannel* voice_channel = it->second.voice_channel;
  if (voice_channel != NULL)
    session_client_->channel_manager()->DestroyVoiceChannel(voice_channel);

  // Destroy data channel
  DataChannel* data_channel = it->second.data_channel;
  if (data_channel != NULL)
    session_client_->channel_manager()->DestroyDataChannel(data_channel);

  delete it->second.recv_streams;
  media_session_map_.erase(it);

  // Destroy speaker monitor
  StopSpeakerMonitor(session);

  // Signal client
  SignalRemoveSession(this, session);

  // The call auto destroys when the last session is removed
  rtc::Thread::Current()->Post(this, MSG_CHECKAUTODESTROY);
}

VoiceChannel* Call::GetVoiceChannel(Session* session) const {
  MediaSessionMap::const_iterator it = media_session_map_.find(session->id());
  return (it != media_session_map_.end()) ? it->second.voice_channel : NULL;
}

VideoChannel* Call::GetVideoChannel(Session* session) const {
  MediaSessionMap::const_iterator it = media_session_map_.find(session->id());
  return (it != media_session_map_.end()) ? it->second.video_channel : NULL;
}

DataChannel* Call::GetDataChannel(Session* session) const {
  MediaSessionMap::const_iterator it = media_session_map_.find(session->id());
  return (it != media_session_map_.end()) ? it->second.data_channel : NULL;
}

MediaStreams* Call::GetMediaStreams(Session* session) const {
  MediaSessionMap::const_iterator it = media_session_map_.find(session->id());
  return (it != media_session_map_.end()) ? it->second.recv_streams : NULL;
}

void Call::EnableChannels(bool enable) {
  MediaSessionMap::iterator it;
  for (it = media_session_map_.begin(); it != media_session_map_.end(); ++it) {
    EnableSessionChannels(it->second.session, enable);
  }
}

void Call::EnableSessionChannels(Session* session, bool enable) {
  MediaSessionMap::iterator it = media_session_map_.find(session->id());
  if (it == media_session_map_.end())
    return;

  VoiceChannel* voice_channel = it->second.voice_channel;
  VideoChannel* video_channel = it->second.video_channel;
  DataChannel* data_channel = it->second.data_channel;
  if (voice_channel != NULL)
    voice_channel->Enable(enable);
  if (video_channel != NULL)
    video_channel->Enable(enable);
  if (data_channel != NULL)
    data_channel->Enable(enable);
}

void Call::Mute(bool mute) {
  muted_ = mute;
  MediaSessionMap::iterator it;
  for (it = media_session_map_.begin(); it != media_session_map_.end(); ++it) {
    if (it->second.voice_channel != NULL)
      it->second.voice_channel->MuteStream(0, mute);
  }
}

void Call::MuteVideo(bool mute) {
  video_muted_ = mute;
  MediaSessionMap::iterator it;
  for (it = media_session_map_.begin(); it != media_session_map_.end(); ++it) {
    if (it->second.video_channel != NULL)
      it->second.video_channel->MuteStream(0, mute);
  }
}

bool Call::SendData(Session* session,
                    const SendDataParams& params,
                    const rtc::Buffer& payload,
                    SendDataResult* result) {
  DataChannel* data_channel = GetDataChannel(session);
  if (!data_channel) {
    LOG(LS_WARNING) << "Could not send data: no data channel.";
    return false;
  }

  return data_channel->SendData(params, payload, result);
}

void Call::PressDTMF(int event) {
  // Queue up this digit
  if (queued_dtmf_.size() < kMaxDTMFDigits) {
    LOG(LS_INFO) << "Call::PressDTMF(" << event << ")";

    queued_dtmf_.push_back(event);

    if (!playing_dtmf_) {
      ContinuePlayDTMF();
    }
  }
}

cricket::VideoFormat ScreencastFormatFromFps(int fps) {
  // The capturer pretty much ignore this, but just in case we give it
  // a resolution big enough to cover any expected desktop.  In any
  // case, it can't be 0x0, or the CaptureManager will fail to use it.
  return cricket::VideoFormat(
      1, 1,
      cricket::VideoFormat::FpsToInterval(fps),
      cricket::FOURCC_ANY);
}

bool Call::StartScreencast(Session* session,
                           const std::string& streamid, uint32 ssrc,
                           const ScreencastId& screenid, int fps) {
  MediaSessionMap::iterator it = media_session_map_.find(session->id());
  if (it == media_session_map_.end()) {
    return false;
  }

  VideoChannel *video_channel = GetVideoChannel(session);
  if (!video_channel) {
    LOG(LS_WARNING) << "Cannot add screencast"
                    << " because there is no video channel.";
    return false;
  }

  VideoCapturer* capturer = session_client_->channel_manager()->
      CreateScreenCapturer(screenid);
  if (!capturer) {
    LOG(LS_WARNING) << "Could not create screencast capturer.";
    return false;
  }

  if (!video_channel->AddScreencast(ssrc, capturer)) {
    delete capturer;
    LOG(LS_WARNING) << "Could not add screencast capturer.";
    return false;
  }

  VideoFormat format = ScreencastFormatFromFps(fps);
  if (!session_client_->channel_manager()->StartVideoCapture(
          capturer, format)) {
    LOG(LS_WARNING) << "Could not start video capture.";
    video_channel->RemoveScreencast(ssrc);
    return false;
  }

  if (!video_channel->SetCapturer(ssrc, capturer)) {
    LOG(LS_WARNING) << "Could not start sending screencast.";
    session_client_->channel_manager()->StopVideoCapture(
        capturer, ScreencastFormatFromFps(fps));
    video_channel->RemoveScreencast(ssrc);
  }

  // TODO(pthatcher): Once the CaptureManager has a nicer interface
  // for removing captures (such as having StartCapture return a
  // handle), remove this StartedCapture stuff.
  it->second.started_screencasts.insert(
      std::make_pair(ssrc, StartedCapture(capturer, format)));

  // TODO(pthatcher): Verify we aren't re-using an existing id or
  // ssrc.
  StreamParams stream;
  stream.id = streamid;
  stream.ssrcs.push_back(ssrc);
  VideoContentDescription* video = CreateVideoStreamUpdate(stream);

  // TODO(pthatcher): Wait until view request before sending video.
  video_channel->SetLocalContent(video, CA_UPDATE, NULL);
  SendVideoStreamUpdate(session, video);
  return true;
}

bool Call::StopScreencast(Session* session,
                          const std::string& streamid, uint32 ssrc) {
  if (!StopScreencastWithoutSendingUpdate(session, ssrc)) {
    return false;
  }

  VideoChannel *video_channel = GetVideoChannel(session);
  if (!video_channel) {
    LOG(LS_WARNING) << "Cannot add screencast"
                    << " because there is no video channel.";
    return false;
  }

  StreamParams stream;
  stream.id = streamid;
  // No ssrcs
  VideoContentDescription* video = CreateVideoStreamUpdate(stream);

  video_channel->SetLocalContent(video, CA_UPDATE, NULL);
  SendVideoStreamUpdate(session, video);
  return true;
}

bool Call::StopScreencastWithoutSendingUpdate(
    Session* session, uint32 ssrc) {
  MediaSessionMap::iterator it = media_session_map_.find(session->id());
  if (it == media_session_map_.end()) {
    return false;
  }

  VideoChannel *video_channel = GetVideoChannel(session);
  if (!video_channel) {
    LOG(LS_WARNING) << "Cannot remove screencast"
                    << " because there is no video channel.";
    return false;
  }

  StartedScreencastMap::const_iterator screencast_iter =
      it->second.started_screencasts.find(ssrc);
  if (screencast_iter == it->second.started_screencasts.end()) {
    LOG(LS_WARNING) << "Could not stop screencast " << ssrc
                    << " because there is no capturer.";
    return false;
  }

  VideoCapturer* capturer = screencast_iter->second.capturer;
  VideoFormat format = screencast_iter->second.format;
  video_channel->SetCapturer(ssrc, NULL);
  if (!session_client_->channel_manager()->StopVideoCapture(
          capturer, format)) {
    LOG(LS_WARNING) << "Could not stop screencast " << ssrc
                    << " because could not stop capture.";
    return false;
  }
  video_channel->RemoveScreencast(ssrc);
  it->second.started_screencasts.erase(ssrc);
  return true;
}

VideoContentDescription* Call::CreateVideoStreamUpdate(
    const StreamParams& stream) {
  VideoContentDescription* video = new VideoContentDescription();
  video->set_multistream(true);
  video->set_partial(true);
  video->AddStream(stream);
  return video;
}

void Call::SendVideoStreamUpdate(
    Session* session, VideoContentDescription* video) {
  // Takes the ownership of |video|.
  rtc::scoped_ptr<VideoContentDescription> description(video);
  const ContentInfo* video_info =
      GetFirstVideoContent(session->local_description());
  if (video_info == NULL) {
    LOG(LS_WARNING) << "Cannot send stream update for video.";
    return;
  }

  std::vector<ContentInfo> contents;
  contents.push_back(
      ContentInfo(video_info->name, video_info->type, description.get()));

  session->SendDescriptionInfoMessage(contents);
}

void Call::ContinuePlayDTMF() {
  playing_dtmf_ = false;

  // Check to see if we have a queued tone
  if (queued_dtmf_.size() > 0) {
    playing_dtmf_ = true;

    int tone = queued_dtmf_.front();
    queued_dtmf_.pop_front();

    LOG(LS_INFO) << "Call::ContinuePlayDTMF(" << tone << ")";
    for (MediaSessionMap::iterator it = media_session_map_.begin();
         it != media_session_map_.end(); ++it) {
      if (it->second.voice_channel != NULL) {
        it->second.voice_channel->PressDTMF(tone, true);
      }
    }

    // Post a message to play the next tone or at least clear the playing_dtmf_
    // bit.
    rtc::Thread::Current()->PostDelayed(kDTMFDelay, this, MSG_PLAYDTMF);
  }
}

void Call::Join(Call* call, bool enable) {
  for (MediaSessionMap::iterator it = call->media_session_map_.begin();
       it != call->media_session_map_.end(); ++it) {
    // Shouldn't already exist.
    ASSERT(media_session_map_.find(it->first) == media_session_map_.end());
    media_session_map_[it->first] = it->second;

    it->second.session->SignalState.connect(this, &Call::OnSessionState);
    it->second.session->SignalError.connect(this, &Call::OnSessionError);
    it->second.session->SignalReceivedTerminateReason
      .connect(this, &Call::OnReceivedTerminateReason);

    EnableSessionChannels(it->second.session, enable);
  }

  // Moved all the sessions over, so the other call should no longer have any.
  call->media_session_map_.clear();
}

void Call::StartConnectionMonitor(Session* session, int cms) {
  VoiceChannel* voice_channel = GetVoiceChannel(session);
  if (voice_channel) {
    voice_channel->SignalConnectionMonitor.connect(this,
        &Call::OnConnectionMonitor);
    voice_channel->StartConnectionMonitor(cms);
  }

  VideoChannel* video_channel = GetVideoChannel(session);
  if (video_channel) {
    video_channel->SignalConnectionMonitor.connect(this,
        &Call::OnConnectionMonitor);
    video_channel->StartConnectionMonitor(cms);
  }
}

void Call::StopConnectionMonitor(Session* session) {
  VoiceChannel* voice_channel = GetVoiceChannel(session);
  if (voice_channel) {
    voice_channel->StopConnectionMonitor();
    voice_channel->SignalConnectionMonitor.disconnect(this);
  }

  VideoChannel* video_channel = GetVideoChannel(session);
  if (video_channel) {
    video_channel->StopConnectionMonitor();
    video_channel->SignalConnectionMonitor.disconnect(this);
  }
}

void Call::StartAudioMonitor(Session* session, int cms) {
  VoiceChannel* voice_channel = GetVoiceChannel(session);
  if (voice_channel) {
    voice_channel->SignalAudioMonitor.connect(this, &Call::OnAudioMonitor);
    voice_channel->StartAudioMonitor(cms);
  }
}

void Call::StopAudioMonitor(Session* session) {
  VoiceChannel* voice_channel = GetVoiceChannel(session);
  if (voice_channel) {
    voice_channel->StopAudioMonitor();
    voice_channel->SignalAudioMonitor.disconnect(this);
  }
}

bool Call::IsAudioMonitorRunning(Session* session) {
  VoiceChannel* voice_channel = GetVoiceChannel(session);
  if (voice_channel) {
    return voice_channel->IsAudioMonitorRunning();
  } else {
    return false;
  }
}

void Call::StartSpeakerMonitor(Session* session) {
  if (speaker_monitor_map_.find(session->id()) == speaker_monitor_map_.end()) {
    if (!IsAudioMonitorRunning(session)) {
      StartAudioMonitor(session, kAudioMonitorPollPeriodMillis);
    }
    CurrentSpeakerMonitor* speaker_monitor =
        new cricket::CurrentSpeakerMonitor(
            audio_source_proxy_.get(), session);
    speaker_monitor->SignalUpdate.connect(this, &Call::OnSpeakerMonitor);
    speaker_monitor->Start();
    speaker_monitor_map_[session->id()] = speaker_monitor;
  } else {
    LOG(LS_WARNING) << "Already started speaker monitor for session "
                    << session->id() << ".";
  }
}

void Call::StopSpeakerMonitor(Session* session) {
  if (speaker_monitor_map_.find(session->id()) == speaker_monitor_map_.end()) {
    LOG(LS_WARNING) << "Speaker monitor for session "
                    << session->id() << " already stopped.";
  } else {
    CurrentSpeakerMonitor* monitor = speaker_monitor_map_[session->id()];
    monitor->Stop();
    speaker_monitor_map_.erase(session->id());
    delete monitor;
  }
}

void Call::OnConnectionMonitor(VoiceChannel* channel,
                               const std::vector<ConnectionInfo> &infos) {
  SignalConnectionMonitor(this, infos);
}

void Call::OnMediaMonitor(VoiceChannel* channel, const VoiceMediaInfo& info) {
  last_voice_media_info_ = info;
  SignalMediaMonitor(this, info);
}

void Call::OnAudioMonitor(VoiceChannel* channel, const AudioInfo& info) {
  SignalAudioMonitor(this, info);
}

void Call::OnSpeakerMonitor(CurrentSpeakerMonitor* monitor, uint32 ssrc) {
  Session* session = static_cast<Session*>(monitor->session());
  MediaStreams* recv_streams = GetMediaStreams(session);
  if (recv_streams) {
    StreamParams stream;
    recv_streams->GetAudioStream(StreamSelector(ssrc), &stream);
    SignalSpeakerMonitor(this, session, stream);
  }
}

void Call::OnConnectionMonitor(VideoChannel* channel,
                               const std::vector<ConnectionInfo> &infos) {
  SignalVideoConnectionMonitor(this, infos);
}

void Call::OnMediaMonitor(VideoChannel* channel, const VideoMediaInfo& info) {
  SignalVideoMediaMonitor(this, info);
}

void Call::OnDataReceived(DataChannel* channel,
                          const ReceiveDataParams& params,
                          const rtc::Buffer& payload) {
  SignalDataReceived(this, params, payload);
}

uint32 Call::id() {
  return id_;
}

void Call::OnSessionState(BaseSession* base_session, BaseSession::State state) {
  Session* session = static_cast<Session*>(base_session);
  switch (state) {
    case Session::STATE_RECEIVEDACCEPT:
      UpdateRemoteMediaStreams(session,
          session->remote_description()->contents(), false);
      session_client_->session_manager()->signaling_thread()->Clear(this,
          MSG_TERMINATECALL);
      break;
    case Session::STATE_RECEIVEDREJECT:
    case Session::STATE_RECEIVEDTERMINATE:
      session_client_->session_manager()->signaling_thread()->Clear(this,
          MSG_TERMINATECALL);
      break;
    default:
      break;
  }
  SignalSessionState(this, session, state);
}

void Call::OnSessionError(BaseSession* base_session, Session::Error error) {
  session_client_->session_manager()->signaling_thread()->Clear(this,
      MSG_TERMINATECALL);
  SignalSessionError(this, static_cast<Session*>(base_session), error);
}

void Call::OnSessionInfoMessage(Session* session,
                                const buzz::XmlElement* action_elem) {
  if (!IsJingleViewRequest(action_elem)) {
    return;
  }

  ViewRequest view_request;
  ParseError error;
  if (!ParseJingleViewRequest(action_elem, &view_request, &error)) {
    LOG(LS_WARNING) << "Failed to parse view request: " << error.text;
    return;
  }

  VideoChannel* video_channel = GetVideoChannel(session);
  if (video_channel == NULL) {
    LOG(LS_WARNING) << "Ignore view request since we have no video channel.";
    return;
  }

  if (!video_channel->ApplyViewRequest(view_request)) {
    LOG(LS_WARNING) << "Failed to ApplyViewRequest.";
  }
}

void Call::OnRemoteDescriptionUpdate(BaseSession* base_session,
                                     const ContentInfos& updated_contents) {
  Session* session = static_cast<Session*>(base_session);

  const ContentInfo* audio_content = GetFirstAudioContent(updated_contents);
  if (audio_content) {
    const AudioContentDescription* audio_update =
        static_cast<const AudioContentDescription*>(audio_content->description);
    if (!audio_update->codecs().empty()) {
      UpdateVoiceChannelRemoteContent(session, audio_update);
    }
  }

  const ContentInfo* video_content = GetFirstVideoContent(updated_contents);
  if (video_content) {
    const VideoContentDescription* video_update =
        static_cast<const VideoContentDescription*>(video_content->description);
    if (!video_update->codecs().empty()) {
      UpdateVideoChannelRemoteContent(session, video_update);
    }
  }

  const ContentInfo* data_content = GetFirstDataContent(updated_contents);
  if (data_content) {
    const DataContentDescription* data_update =
        static_cast<const DataContentDescription*>(data_content->description);
    if (!data_update->codecs().empty()) {
      UpdateDataChannelRemoteContent(session, data_update);
    }
  }

  UpdateRemoteMediaStreams(session, updated_contents, true);
}

bool Call::UpdateVoiceChannelRemoteContent(
    Session* session, const AudioContentDescription* audio) {
  VoiceChannel* voice_channel = GetVoiceChannel(session);
  if (!voice_channel->SetRemoteContent(audio, CA_UPDATE, NULL)) {
    const std::string error_desc =
        "Failure in audio SetRemoteContent with CA_UPDATE";
    LOG(LS_ERROR) << error_desc;
    session->SetError(BaseSession::ERROR_CONTENT, error_desc);
    return false;
  }
  return true;
}

bool Call::UpdateVideoChannelRemoteContent(
    Session* session, const VideoContentDescription* video) {
  VideoChannel* video_channel = GetVideoChannel(session);
  if (!video_channel->SetRemoteContent(video, CA_UPDATE, NULL)) {
    const std::string error_desc =
        "Failure in video SetRemoteContent with CA_UPDATE";
    LOG(LS_ERROR) << error_desc;
    session->SetError(BaseSession::ERROR_CONTENT, error_desc);
    return false;
  }
  return true;
}

bool Call::UpdateDataChannelRemoteContent(
    Session* session, const DataContentDescription* data) {
  DataChannel* data_channel = GetDataChannel(session);
  if (!data_channel->SetRemoteContent(data, CA_UPDATE, NULL)) {
    const std::string error_desc =
        "Failure in data SetRemoteContent with CA_UPDATE";
    LOG(LS_ERROR) << error_desc;
    session->SetError(BaseSession::ERROR_CONTENT, error_desc);
    return false;
  }
  return true;
}

void Call::UpdateRemoteMediaStreams(Session* session,
                                    const ContentInfos& updated_contents,
                                    bool update_channels) {
  MediaStreams* recv_streams = GetMediaStreams(session);
  if (!recv_streams)
    return;

  cricket::MediaStreams added_streams;
  cricket::MediaStreams removed_streams;

  const ContentInfo* audio_content = GetFirstAudioContent(updated_contents);
  if (audio_content) {
    const AudioContentDescription* audio_update =
        static_cast<const AudioContentDescription*>(audio_content->description);
    UpdateRecvStreams(audio_update->streams(),
                      update_channels ? GetVoiceChannel(session) : NULL,
                      recv_streams->mutable_audio(),
                      added_streams.mutable_audio(),
                      removed_streams.mutable_audio());
  }

  const ContentInfo* video_content = GetFirstVideoContent(updated_contents);
  if (video_content) {
    const VideoContentDescription* video_update =
        static_cast<const VideoContentDescription*>(video_content->description);
    UpdateRecvStreams(video_update->streams(),
                      update_channels ? GetVideoChannel(session) : NULL,
                      recv_streams->mutable_video(),
                      added_streams.mutable_video(),
                      removed_streams.mutable_video());
  }

  const ContentInfo* data_content = GetFirstDataContent(updated_contents);
  if (data_content) {
    const DataContentDescription* data_update =
        static_cast<const DataContentDescription*>(data_content->description);
    UpdateRecvStreams(data_update->streams(),
                      update_channels ? GetDataChannel(session) : NULL,
                      recv_streams->mutable_data(),
                      added_streams.mutable_data(),
                      removed_streams.mutable_data());
  }

  if (!added_streams.empty() || !removed_streams.empty()) {
    SignalMediaStreamsUpdate(this, session, added_streams, removed_streams);
  }
}

void FindStreamChanges(const std::vector<StreamParams>& streams,
                       const std::vector<StreamParams>& updates,
                       std::vector<StreamParams>* added_streams,
                       std::vector<StreamParams>* removed_streams) {
  for (std::vector<StreamParams>::const_iterator update = updates.begin();
       update != updates.end(); ++update) {
    const StreamParams* stream =
        GetStreamByIds(streams, update->groupid, update->id);
    if (stream) {
      if (!update->has_ssrcs()) {
        removed_streams->push_back(*stream);
      }
    } else {
      // There's a bug on reflector that will send <stream>s even
      // though there is not ssrc (which means there isn't really a
      // stream).  To work around it, we simply ignore new <stream>s
      // that don't have any ssrcs.
      if (update->has_ssrcs()) {
        added_streams->push_back(*update);
      }
    }
  }
}

void Call::UpdateRecvStreams(const std::vector<StreamParams>& update_streams,
                             BaseChannel* channel,
                             std::vector<StreamParams>* recv_streams,
                             std::vector<StreamParams>* added_streams,
                             std::vector<StreamParams>* removed_streams) {
  FindStreamChanges(*recv_streams,
                    update_streams, added_streams, removed_streams);
  AddRecvStreams(*added_streams,
                 channel, recv_streams);
  RemoveRecvStreams(*removed_streams,
                    channel, recv_streams);
}

void Call::AddRecvStreams(const std::vector<StreamParams>& added_streams,
                          BaseChannel* channel,
                          std::vector<StreamParams>* recv_streams) {
  std::vector<StreamParams>::const_iterator stream;
  for (stream = added_streams.begin();
       stream != added_streams.end();
       ++stream) {
    AddRecvStream(*stream, channel, recv_streams);
  }
}

void Call::AddRecvStream(const StreamParams& stream,
                         BaseChannel* channel,
                         std::vector<StreamParams>* recv_streams) {
  if (channel && stream.has_ssrcs()) {
    channel->AddRecvStream(stream);
  }
  recv_streams->push_back(stream);
}

void Call::RemoveRecvStreams(const std::vector<StreamParams>& removed_streams,
                             BaseChannel* channel,
                             std::vector<StreamParams>* recv_streams) {
  std::vector<StreamParams>::const_iterator stream;
  for (stream = removed_streams.begin();
       stream != removed_streams.end();
       ++stream) {
    RemoveRecvStream(*stream, channel, recv_streams);
  }
}

void Call::RemoveRecvStream(const StreamParams& stream,
                            BaseChannel* channel,
                            std::vector<StreamParams>* recv_streams) {
  if (channel && stream.has_ssrcs()) {
    // TODO(pthatcher): Change RemoveRecvStream to take a stream argument.
    channel->RemoveRecvStream(stream.first_ssrc());
  }
  RemoveStreamByIds(recv_streams, stream.groupid, stream.id);
}

void Call::OnReceivedTerminateReason(Session* session,
                                     const std::string& reason) {
  session_client_->session_manager()->signaling_thread()->Clear(this,
    MSG_TERMINATECALL);
  SignalReceivedTerminateReason(this, session, reason);
}

// TODO(mdodd): Get ride of this method since all Hangouts are using a secure
// connection.
bool Call::secure() const {
  if (session_client_->secure() == SEC_DISABLED) {
    return false;
  }

  bool ret = true;
  int i = 0;

  MediaSessionMap::const_iterator it;
  for (it = media_session_map_.begin(); it != media_session_map_.end(); ++it) {
    LOG_F(LS_VERBOSE) << "session[" << i
                      << "], check local and remote descriptions";
    i++;

    if (!SessionDescriptionContainsCrypto(
            it->second.session->local_description()) ||
        !SessionDescriptionContainsCrypto(
            it->second.session->remote_description())) {
      ret = false;
      break;
    }
  }

  LOG_F(LS_VERBOSE) << "secure=" << ret;
  return ret;
}

bool Call::SessionDescriptionContainsCrypto(
    const SessionDescription* sdesc) const {
  if (sdesc == NULL) {
    LOG_F(LS_VERBOSE) << "sessionDescription is NULL";
    return false;
  }

  return ContentContainsCrypto(sdesc->GetContentByName(CN_AUDIO)) &&
         ContentContainsCrypto(sdesc->GetContentByName(CN_VIDEO));
}

Session* Call::InternalInitiateSession(const std::string& id,
                                       const buzz::Jid& to,
                                       const std::string& initiator_name,
                                       const CallOptions& options) {
  const SessionDescription* offer = session_client_->CreateOffer(options);

  Session* session = session_client_->CreateSession(id, this);
  // Only override the initiator_name if it was manually supplied. Otherwise,
  // session_client_ will supply the local jid as initiator in CreateOffer.
  if (!initiator_name.empty()) {
    session->set_initiator_name(initiator_name);
  }

  AddSession(session, offer);
  session->Initiate(to.Str(), offer);

  // After this timeout, terminate the call because the callee isn't
  // answering
  session_client_->session_manager()->signaling_thread()->Clear(this,
      MSG_TERMINATECALL);
  session_client_->session_manager()->signaling_thread()->PostDelayed(
    send_to_voicemail_ ? kSendToVoicemailTimeout : kNoVoicemailTimeout,
    this, MSG_TERMINATECALL);
  return session;
}

AudioSourceProxy* Call::GetAudioSourceProxy() {
  return audio_source_proxy_.get();
}

}  // namespace cricket
