/*
 * libjingle
 * Copyright 2004--2011, 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 "talk/app/webrtcv1/webrtcsession.h"

#include <string>
#include <vector>

#include "talk/base/common.h"
#include "talk/base/scoped_ptr.h"
#include "talk/p2p/base/constants.h"
#include "talk/p2p/base/sessiondescription.h"
#include "talk/p2p/base/p2ptransport.h"
#include "talk/session/phone/channel.h"
#include "talk/session/phone/channelmanager.h"
#include "talk/session/phone/mediasessionclient.h"
#include "talk/session/phone/voicechannel.h"

namespace webrtc {

enum {
  MSG_CANDIDATE_TIMEOUT = 101,
};

static const int kAudioMonitorPollFrequency = 100;
static const int kMonitorPollFrequency = 1000;

// We allow 30 seconds to establish a connection; beyond that we consider
// it an error
static const int kCallSetupTimeout = 30 * 1000;
// A loss of connectivity is probably due to the Internet connection going
// down, and it might take a while to come back on wireless networks, so we
// use a longer timeout for that.
static const int kCallLostTimeout = 60 * 1000;

static const char kVideoStream[] = "video_rtp";
static const char kAudioStream[] = "rtp";

static const int kDefaultVideoCodecId = 100;
static const int kDefaultVideoCodecFramerate = 30;
static const char kDefaultVideoCodecName[] = "VP8";

WebRtcSession::WebRtcSession(const std::string& id,
                             bool incoming,
                             cricket::PortAllocator* allocator,
                             cricket::ChannelManager* channelmgr,
                             talk_base::Thread* signaling_thread)
    : BaseSession(signaling_thread, channelmgr->worker_thread(),
                  allocator, id, "", !incoming),
      transport_(NULL),
      channel_manager_(channelmgr),
      transports_writable_(false),
      muted_(false),
      camera_muted_(false),
      setup_timeout_(kCallSetupTimeout),
      signaling_thread_(signaling_thread),
      incoming_(incoming),
      port_allocator_(allocator),
      desc_factory_(channel_manager_) {
}

WebRtcSession::~WebRtcSession() {
  RemoveAllStreams();
  // TODO: Do we still need Terminate?
  // if (state_ != STATE_RECEIVEDTERMINATE) {
  //   Terminate();
  // }
  if (transport_) {
    delete transport_;
    transport_ = NULL;
  }
}

bool WebRtcSession::Initiate() {
  const cricket::VideoCodec default_codec(kDefaultVideoCodecId,
      kDefaultVideoCodecName, kDefaultVideoCodecWidth, kDefaultVideoCodecHeight,
      kDefaultVideoCodecFramerate, 0);
  channel_manager_->SetDefaultVideoEncoderConfig(
      cricket::VideoEncoderConfig(default_codec));

  if (signaling_thread_ == NULL)
    return false;

  transport_ = CreateTransport();

  if (transport_ == NULL)
    return false;

  transport_->set_allow_local_ips(true);

  // start transports
  transport_->SignalRequestSignaling.connect(
      this, &WebRtcSession::OnRequestSignaling);
  transport_->SignalCandidatesReady.connect(
      this, &WebRtcSession::OnCandidatesReady);
  transport_->SignalWritableState.connect(
      this, &WebRtcSession::OnWritableState);
  // Limit the amount of time that setting up a call may take.
  StartTransportTimeout(kCallSetupTimeout);
  return true;
}

cricket::Transport* WebRtcSession::CreateTransport() {
  ASSERT(signaling_thread()->IsCurrent());
  return new cricket::P2PTransport(
      talk_base::Thread::Current(),
      channel_manager_->worker_thread(), port_allocator());
}

bool WebRtcSession::CreateVoiceChannel(const std::string& stream_id) {
  // RTCP disabled
  cricket::VoiceChannel* voice_channel =
      channel_manager_->CreateVoiceChannel(this, stream_id, true);
  if (voice_channel == NULL) {
    LOG(LERROR) << "Unable to create voice channel.";
    return false;
  }
  StreamInfo* stream_info = new StreamInfo(stream_id);
  stream_info->channel = voice_channel;
  stream_info->video = false;
  streams_.push_back(stream_info);
  return true;
}

bool WebRtcSession::CreateVideoChannel(const std::string& stream_id) {
  // RTCP disabled
  cricket::VideoChannel* video_channel =
      channel_manager_->CreateVideoChannel(this, stream_id, true, NULL);
  if (video_channel == NULL) {
    LOG(LERROR) << "Unable to create video channel.";
    return false;
  }
  StreamInfo* stream_info = new StreamInfo(stream_id);
  stream_info->channel = video_channel;
  stream_info->video = true;
  streams_.push_back(stream_info);
  return true;
}

cricket::TransportChannel* WebRtcSession::CreateChannel(
    const std::string& content_name,
    const std::string& name) {
  if (!transport_) {
    return NULL;
  }
  std::string type;
  if (content_name.compare(kVideoStream) == 0) {
    type = cricket::NS_GINGLE_VIDEO;
  } else {
    type = cricket::NS_GINGLE_AUDIO;
  }
  cricket::TransportChannel* transport_channel =
      transport_->CreateChannel(name, type);
  ASSERT(transport_channel != NULL);
  return transport_channel;
}

cricket::TransportChannel* WebRtcSession::GetChannel(
    const std::string& content_name, const std::string& name) {
  if (!transport_)
    return NULL;

  return transport_->GetChannel(name);
}

void WebRtcSession::DestroyChannel(
    const std::string& content_name, const std::string& name) {
  if (!transport_)
    return;

  transport_->DestroyChannel(name);
}

void WebRtcSession::OnMessage(talk_base::Message* message) {
  switch (message->message_id) {
    case MSG_CANDIDATE_TIMEOUT:
      if (transport_->writable()) {
        // This should never happen: The timout triggered even
        // though a call was successfully set up.
        ASSERT(false);
      }
      SignalFailedCall();
      break;
    default:
      cricket::BaseSession::OnMessage(message);
      break;
  }
}

bool WebRtcSession::Connect() {
  if (streams_.empty()) {
    // nothing to initiate
    return false;
  }
  // lets connect all the transport channels created before for this session
  transport_->ConnectChannels();

  // create an offer now. This is to call SetState
  // Actual offer will be send when OnCandidatesReady callback received
  cricket::SessionDescription* offer = CreateOffer();
  set_local_description(offer);
  SetState((incoming()) ? STATE_SENTACCEPT : STATE_SENTINITIATE);

  // Enable all the channels
  EnableAllStreams();
  SetVideoCapture(true);
  return true;
}

bool WebRtcSession::SetVideoRenderer(const std::string& stream_id,
                                     cricket::VideoRenderer* renderer) {
  bool ret = false;
  StreamMap::iterator iter;
  for (iter = streams_.begin(); iter != streams_.end(); ++iter) {
    StreamInfo* stream_info = (*iter);
    if (stream_info->stream_id.compare(stream_id) == 0) {
      ASSERT(stream_info->channel != NULL);
      ASSERT(stream_info->video);
      cricket::VideoChannel* channel = static_cast<cricket::VideoChannel*>(
          stream_info->channel);
      ret = channel->SetRenderer(0, renderer);
      break;
    }
  }
  return ret;
}

bool WebRtcSession::SetVideoCapture(bool capture) {
  channel_manager_->SetVideoCapture(capture);
  return true;
}

bool WebRtcSession::RemoveStream(const std::string& stream_id) {
  bool ret = false;
  StreamMap::iterator iter;
  for (iter = streams_.begin(); iter != streams_.end(); ++iter) {
    StreamInfo* sinfo = (*iter);
    if (sinfo->stream_id.compare(stream_id) == 0) {
      if (!sinfo->video) {
        cricket::VoiceChannel* channel = static_cast<cricket::VoiceChannel*> (
            sinfo->channel);
        channel->Enable(false);
        // Note: If later the channel is used by multiple streams, then we
        // should not destroy the channel until all the streams are removed.
        channel_manager_->DestroyVoiceChannel(channel);
      } else {
        cricket::VideoChannel* channel = static_cast<cricket::VideoChannel*> (
            sinfo->channel);
        channel->Enable(false);
        // Note: If later the channel is used by multiple streams, then we
        // should not destroy the channel until all the streams are removed.
        channel_manager_->DestroyVideoChannel(channel);
      }
      // channel and transport will be deleted in
      // DestroyVoiceChannel/DestroyVideoChannel
      streams_.erase(iter);
      ret = true;
      break;
    }
  }
  if (!ret) {
    LOG(LERROR) << "No streams found for stream id " << stream_id;
    // TODO: trigger onError callback
  }
  return ret;
}

void WebRtcSession::EnableAllStreams() {
  StreamMap::const_iterator i;
  for (i = streams_.begin(); i != streams_.end(); ++i) {
    cricket::BaseChannel* channel = (*i)->channel;
    if (channel)
      channel->Enable(true);
  }
}

void WebRtcSession::RemoveAllStreams() {
  SetState(STATE_RECEIVEDTERMINATE);

  // signaling_thread_->Post(this, MSG_RTC_REMOVEALLSTREAMS);
  // First build a list of streams to remove and then remove them.
  // The reason we do this is that if we remove the streams inside the
  // loop, a stream might get removed while we're enumerating and the iterator
  // will become invalid (and we crash).
  // streams_ entry will be removed from ChannelManager callback method
  // DestroyChannel
  std::vector<std::string> streams_to_remove;
  StreamMap::iterator iter;
  for (iter = streams_.begin(); iter != streams_.end(); ++iter)
    streams_to_remove.push_back((*iter)->stream_id);

  for (std::vector<std::string>::iterator i = streams_to_remove.begin();
       i != streams_to_remove.end(); ++i) {
    RemoveStream(*i);
  }
}

bool WebRtcSession::HasStream(const std::string& stream_id) const {
  StreamMap::const_iterator iter;
  for (iter = streams_.begin(); iter != streams_.end(); ++iter) {
    StreamInfo* sinfo = (*iter);
    if (stream_id.compare(sinfo->stream_id) == 0) {
      return true;
    }
  }
  return false;
}

bool WebRtcSession::HasChannel(bool video) const {
  StreamMap::const_iterator iter;
  for (iter = streams_.begin(); iter != streams_.end(); ++iter) {
    StreamInfo* sinfo = (*iter);
    if (sinfo->video == video) {
      return true;
    }
  }
  return false;
}

bool WebRtcSession::HasAudioChannel() const {
  return HasChannel(false);
}

bool WebRtcSession::HasVideoChannel() const {
  return HasChannel(true);
}

void WebRtcSession::OnRequestSignaling(cricket::Transport* transport) {
  transport->OnSignalingReady();
}

void WebRtcSession::OnWritableState(cricket::Transport* transport) {
  ASSERT(transport == transport_);
  const bool transports_writable = transport_->writable();
  if (transports_writable) {
    if (transports_writable != transports_writable_) {
      signaling_thread_->Clear(this, MSG_CANDIDATE_TIMEOUT);
    } else {
      // At one point all channels were writable and we had full connectivity,
      // but then we lost it. Start the timeout again to kill the call if it
      // doesn't come back.
      StartTransportTimeout(kCallLostTimeout);
    }
    transports_writable_ = transports_writable;
  }
  NotifyTransportState();
  return;
}

void WebRtcSession::StartTransportTimeout(int timeout) {
  talk_base::Thread::Current()->PostDelayed(timeout, this,
                                            MSG_CANDIDATE_TIMEOUT,
                                            NULL);
}

void WebRtcSession::NotifyTransportState() {
}

bool WebRtcSession::OnInitiateMessage(
    cricket::SessionDescription* offer,
    const std::vector<cricket::Candidate>& candidates) {
  if (!offer) {
    LOG(LERROR) << "No SessionDescription from peer";
    return false;
  }

  // Get capabilities from offer before generating an answer to it.
  cricket::MediaSessionOptions options;
  if (GetFirstAudioContent(offer))
    options.has_audio = true;
  if (GetFirstVideoContent(offer))
    options.has_video = true;

  talk_base::scoped_ptr<cricket::SessionDescription> answer;
  answer.reset(CreateAnswer(offer, options));

  if (!answer.get()) {
    return false;
  }

  const cricket::ContentInfo* audio_content = GetFirstAudioContent(
      answer.get());
  const cricket::ContentInfo* video_content = GetFirstVideoContent(
      answer.get());

  if (!audio_content && !video_content) {
    return false;
  }

  bool ret = true;
  if (audio_content) {
    ret = !HasAudioChannel() &&
          CreateVoiceChannel(audio_content->name);
    if (!ret) {
      LOG(LERROR) << "Failed to create voice channel for "
                  << audio_content->name;
      return false;
    }
  }

  if (video_content) {
    ret = !HasVideoChannel() &&
          CreateVideoChannel(video_content->name);
    if (!ret) {
      LOG(LERROR) << "Failed to create video channel for "
                  << video_content->name;
      return false;
    }
  }
  // Provide remote candidates to the transport
  transport_->OnRemoteCandidates(candidates);

  set_remote_description(offer);
  SetState(STATE_RECEIVEDINITIATE);

  transport_->ConnectChannels();
  EnableAllStreams();

  set_local_description(answer.release());

  // AddStream called only once with Video label
  if (video_content) {
    SignalAddStream(video_content->name, true);
  } else {
    SignalAddStream(audio_content->name, false);
  }
  SetState(STATE_SENTACCEPT);
  return true;
}

bool WebRtcSession::OnRemoteDescription(
    cricket::SessionDescription* desc,
    const std::vector<cricket::Candidate>& candidates) {
  if (state() == STATE_SENTACCEPT ||
      state() == STATE_RECEIVEDACCEPT ||
      state() == STATE_INPROGRESS) {
    transport_->OnRemoteCandidates(candidates);
    return true;
  }
  // Session description is always accepted.
  set_remote_description(desc);
  SetState(STATE_RECEIVEDACCEPT);
  // Will trigger OnWritableState() if successful.
  transport_->OnRemoteCandidates(candidates);

  if (!incoming()) {
    // Trigger OnAddStream callback at the initiator
    const cricket::ContentInfo* video_content = GetFirstVideoContent(desc);
    if (video_content && !SendSignalAddStream(true)) {
      LOG(LERROR) << "Video stream unexpected in answer.";
      return false;
    } else {
      const cricket::ContentInfo* audio_content = GetFirstAudioContent(desc);
      if (audio_content && !SendSignalAddStream(false)) {
        LOG(LERROR) << "Audio stream unexpected in answer.";
        return false;
      }
    }
  }
  return true;
}

// Send the SignalAddStream with the stream_id based on the content type.
bool WebRtcSession::SendSignalAddStream(bool video) {
  StreamMap::const_iterator iter;
  for (iter = streams_.begin(); iter != streams_.end(); ++iter) {
    StreamInfo* sinfo = (*iter);
    if (sinfo->video == video) {
      SignalAddStream(sinfo->stream_id, video);
      return true;
    }
  }
  return false;
}

cricket::SessionDescription* WebRtcSession::CreateOffer() {
  cricket::MediaSessionOptions options;
  options.has_audio = false;  // disable default option
  StreamMap::const_iterator iter;
  for (iter = streams_.begin(); iter != streams_.end(); ++iter) {
    if ((*iter)->video) {
      options.has_video = true;
    } else {
      options.has_audio = true;
    }
  }
  // We didn't save the previous offer.
  const cricket::SessionDescription* previous_offer = NULL;
  return desc_factory_.CreateOffer(options, previous_offer);
}

cricket::SessionDescription* WebRtcSession::CreateAnswer(
    const cricket::SessionDescription* offer,
    const cricket::MediaSessionOptions& options) {
  // We didn't save the previous answer.
  const cricket::SessionDescription* previous_answer = NULL;
  return desc_factory_.CreateAnswer(offer, options, previous_answer);
}

void WebRtcSession::SetError(Error error) {
  BaseSession::SetError(error);
}

void WebRtcSession::OnCandidatesReady(
    cricket::Transport* transport,
    const std::vector<cricket::Candidate>& candidates) {
  std::vector<cricket::Candidate>::const_iterator iter;
  for (iter = candidates.begin(); iter != candidates.end(); ++iter) {
    local_candidates_.push_back(*iter);
  }
  SignalLocalDescription(local_description(), candidates);
}
} /* namespace webrtc */
