/*
 * 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 <stdio.h>

#include <list>

#include "base/gunit.h"
#include "base/helpers.h"
#include "talk/app/webrtc/unittest_utilities.h"
#include "talk/app/webrtc/webrtcsession.h"
#include "talk/base/fakenetwork.h"
#include "talk/base/scoped_ptr.h"
#include "talk/base/thread.h"
#include "talk/p2p/base/portallocator.h"
#include "talk/p2p/base/sessiondescription.h"
#include "talk/p2p/client/fakeportallocator.h"
#include "talk/session/phone/fakesession.h"
#include "talk/session/phone/mediasessionclient.h"

class WebRtcSessionTest
    : public sigslot::has_slots<>,
      public testing::Test {
 public:
  enum CallbackId {
    kNone,
    kOnAddStream,
    kOnRemoveStream,
    kOnRtcMediaChannelCreated,
    kOnLocalDescription,
    kOnFailedCall,
  };

  WebRtcSessionTest()
      : callback_ids_(),
        last_stream_id_(""),
        last_was_video_(false),
        last_description_ptr_(NULL),
        last_candidates_(),
        session_(NULL),
        id_(),
        receiving_(false),
        allocator_(NULL),
        channel_manager_(NULL),
        worker_thread_(NULL),
        signaling_thread_(NULL) {
  }

  ~WebRtcSessionTest() {
    session_.reset();
  }

  void OnAddStream(const std::string& stream_id, bool video) {
    callback_ids_.push_back(kOnAddStream);
    last_stream_id_ = stream_id;
    last_was_video_ = video;
  }
  void OnRemoveStream(const std::string& stream_id, bool video) {
    callback_ids_.push_back(kOnRemoveStream);
    last_stream_id_ = stream_id;
    last_was_video_ = video;
  }
  void OnRtcMediaChannelCreated(const std::string& stream_id,
                                        bool video) {
    callback_ids_.push_back(kOnRtcMediaChannelCreated);
    last_stream_id_ = stream_id;
    last_was_video_ = video;
  }
  void OnLocalDescription(
      const cricket::SessionDescription* desc,
      const std::vector<cricket::Candidate>& candidates) {
    callback_ids_.push_back(kOnLocalDescription);
    last_description_ptr_.reset(CopySessionDescription(desc));
    CopyCandidates(candidates, &last_candidates_);
  }
  cricket::SessionDescription* GetLocalDescription(
      std::vector<cricket::Candidate>* candidates) {
    if (last_candidates_.empty()) {
      return NULL;
    }
    if (!last_description_ptr_.get()) {
      return NULL;
    }
    CopyCandidates(last_candidates_, candidates);
    return CopySessionDescription(last_description_ptr_.get());
  }

  void OnFailedCall() {
    callback_ids_.push_back(kOnFailedCall);
  }

  CallbackId PopOldestCallback() {
    if (callback_ids_.empty()) {
      return kNone;
    }
    const CallbackId return_value = callback_ids_.front();
    callback_ids_.pop_front();
    return return_value;
  }

  CallbackId PeekOldestCallback() {
    if (callback_ids_.empty()) {
      return kNone;
    }
    const CallbackId return_value = callback_ids_.front();
    return return_value;
  }

  void Reset() {
    callback_ids_.clear();
    last_stream_id_ = "";
    last_was_video_ = false;
    last_description_ptr_.reset();
    last_candidates_.clear();
  }

  bool WaitForCallback(CallbackId id, int timeout_ms) {
    bool success = false;
    for (int ms = 0; ms < timeout_ms; ms++) {
      const CallbackId peek_id = PeekOldestCallback();
      if (peek_id == id) {
        PopOldestCallback();
        success = true;
        break;
      } else if (peek_id != kNone) {
        success = false;
        break;
      }
      talk_base::Thread::Current()->ProcessMessages(1);
    }
    return success;
  }

  bool Init(bool receiving) {
    if (signaling_thread_ != NULL)
        return false;
    signaling_thread_ = talk_base::Thread::Current();
    receiving_ = receiving;

    if (worker_thread_!= NULL)
        return false;
    worker_thread_ = talk_base::Thread::Current();

    cricket::FakePortAllocator* fake_port_allocator =
        new cricket::FakePortAllocator(worker_thread_, NULL);

    allocator_.reset(static_cast<cricket::PortAllocator*>(fake_port_allocator));

    channel_manager_.reset(new cricket::ChannelManager(worker_thread_));
    if (!channel_manager_->Init())
      return false;

    talk_base::CreateRandomString(8, &id_);

    session_.reset(new webrtc::WebRtcSession(
        id_, receiving_ , allocator_.get(),
        channel_manager_.get(),
        signaling_thread_));
    session_->SignalAddStream.connect(this, &WebRtcSessionTest::OnAddStream);
    session_->SignalRemoveStream.connect(this,
        &WebRtcSessionTest::OnRemoveStream);
    session_->SignalRtcMediaChannelCreated.connect(this,
        &WebRtcSessionTest::OnRtcMediaChannelCreated);
    session_->SignalLocalDescription.connect(this,
        &WebRtcSessionTest::OnLocalDescription);
    session_->SignalFailedCall.connect(this, &WebRtcSessionTest::OnFailedCall);
    return true;
  }

  // All session APIs must be called from the signaling thread.
  bool CallInitiate() {
    return session_->Initiate();
  }

  bool CallConnect() {
    if (!session_->Connect())
      return false;
    // This callback does not happen with FakeTransport!
    if (!WaitForCallback(kOnLocalDescription, 1000)) {
      return false;
    }
    return true;
  }

  bool CallOnRemoteDescription(
      cricket::SessionDescription* description,
      std::vector<cricket::Candidate> candidates) {
    if (!session_->OnRemoteDescription(description, candidates)) {
      return false;
    }
    if (!WaitForCallback(kOnAddStream, 1000)) {
      return false;
    }
    return true;
  }

  bool CallOnInitiateMessage(
      cricket::SessionDescription* description,
      const std::vector<cricket::Candidate>& candidates) {
    if (!session_->OnInitiateMessage(description, candidates)) {
      return false;
    }
    if (!WaitForCallback(kOnAddStream, 1000)) {
      return false;
    }
    return true;
  }

  bool CallCreateVoiceChannel(const std::string& stream_id) {
    if (!session_->CreateVoiceChannel(stream_id)) {
      return false;
    }
    if (!WaitForCallback(kOnRtcMediaChannelCreated, 1000)) {
      return false;
    }
    return true;
  }

  bool CallCreateVideoChannel(const std::string& stream_id) {
    if (!session_->CreateVideoChannel(stream_id)) {
      return false;
    }
    if (!WaitForCallback(kOnRtcMediaChannelCreated, 1000)) {
      return false;
    }
    return true;
  }

  bool CallRemoveStream(const std::string& stream_id) {
    return session_->RemoveStream(stream_id);
  }

  void CallRemoveAllStreams() {
    session_->RemoveAllStreams();
  }

  bool CallHasChannel(const std::string& label) {
    return session_->HasStream(label);
  }

  bool CallHasChannel(bool video) {
    return session_->HasChannel(video);
  }

  bool CallHasAudioChannel() {
    return session_->HasAudioChannel();
  }

  bool CallHasVideoChannel() {
    return session_->HasVideoChannel();
  }

  bool CallSetVideoRenderer(const std::string& stream_id,
                            cricket::VideoRenderer* renderer) {
    return session_->SetVideoRenderer(stream_id, renderer);
  }

  const std::vector<cricket::Candidate>& CallLocalCandidates() {
    return session_->local_candidates();
  }

 private:
  std::list<CallbackId> callback_ids_;

  std::string last_stream_id_;
  bool last_was_video_;
  talk_base::scoped_ptr<cricket::SessionDescription> last_description_ptr_;
  std::vector<cricket::Candidate> last_candidates_;

  talk_base::scoped_ptr<webrtc::WebRtcSession> session_;
  std::string id_;
  bool receiving_;

  talk_base::scoped_ptr<cricket::PortAllocator> allocator_;

  talk_base::scoped_ptr<cricket::ChannelManager> channel_manager_;

  talk_base::Thread* worker_thread_;
  talk_base::Thread* signaling_thread_;
};

bool CallbackReceived(WebRtcSessionTest* session, int timeout) {
  EXPECT_EQ_WAIT(WebRtcSessionTest::kNone, session->PeekOldestCallback(),
                 timeout);
  const WebRtcSessionTest::CallbackId peek_id =
      session->PeekOldestCallback();
  return peek_id != WebRtcSessionTest::kNone;
}

TEST_F(WebRtcSessionTest, InitializationReceiveSanity) {
  const bool kReceiving = true;
  ASSERT_TRUE(Init(kReceiving));
  ASSERT_TRUE(CallInitiate());

  // Should return false because no stream has been set up yet.
  EXPECT_FALSE(CallConnect());
  const bool kVideo = true;
  EXPECT_FALSE(CallHasChannel(kVideo));
  EXPECT_FALSE(CallHasChannel(!kVideo));

  EXPECT_EQ(kNone, PopOldestCallback());
}

TEST_F(WebRtcSessionTest, AudioSendCallSetUp) {
  const bool kReceiving = false;
  ASSERT_TRUE(Init(kReceiving));

  ASSERT_TRUE(CallInitiate());

  ASSERT_TRUE(CallCreateVoiceChannel("Audio"));
  ASSERT_TRUE(CallConnect());

  std::vector<cricket::Candidate> candidates;
  cricket::SessionDescription* local_session = GetLocalDescription(
      &candidates);
  ASSERT_FALSE(candidates.empty());
  ASSERT_FALSE(local_session == NULL);
  if (!CallOnRemoteDescription(local_session, candidates)) {
      delete local_session;
      FAIL();
  }

  // All callbacks should be caught. Assert it.
  ASSERT_FALSE(CallbackReceived(this, 1000));
  ASSERT_TRUE(CallHasAudioChannel() &&
              !CallHasVideoChannel());
}

TEST_F(WebRtcSessionTest, VideoSendCallSetUp) {
  const bool kReceiving = false;
  ASSERT_TRUE(Init(kReceiving));

  ASSERT_TRUE(CallInitiate());

  ASSERT_TRUE(CallCreateVideoChannel("Video"));
  ASSERT_TRUE(CallConnect());

  std::vector<cricket::Candidate> candidates;
  cricket::SessionDescription* local_session = GetLocalDescription(
      &candidates);
  ASSERT_FALSE(candidates.empty());
  ASSERT_FALSE(local_session == NULL);

  if (!CallOnRemoteDescription(local_session, candidates)) {
      delete local_session;
      FAIL();
  }

  // All callbacks should be caught. Assert it.
  ASSERT_FALSE(CallbackReceived(this, 1000));
  ASSERT_TRUE(!CallHasAudioChannel() &&
              CallHasVideoChannel());
}

TEST_F(WebRtcSessionTest, AudioReceiveCallSetUp) {
  const bool kReceiving = true;
  const bool video = false;

  ASSERT_TRUE(Init(kReceiving));

  std::vector<cricket::Candidate> candidates;
  cricket::SessionDescription* local_session =
      GenerateFakeSession(video, &candidates);
  ASSERT_FALSE(candidates.empty());
  ASSERT_FALSE(local_session == NULL);
  ASSERT_TRUE(CallInitiate());
  if (!CallOnInitiateMessage(local_session, candidates)) {
    delete local_session;
    FAIL();
  }
  ASSERT_TRUE(CallConnect());
  ASSERT_FALSE(CallbackReceived(this, 1000));

  ASSERT_TRUE(CallHasAudioChannel() &&
              !CallHasVideoChannel());
}

TEST_F(WebRtcSessionTest, VideoReceiveCallSetUp) {
  const bool kReceiving = true;
  const bool video = true;

  ASSERT_TRUE(Init(kReceiving));

  std::vector<cricket::Candidate> candidates;
  cricket::SessionDescription* local_session =
      GenerateFakeSession(video, &candidates);
  ASSERT_FALSE(candidates.empty());
  ASSERT_FALSE(local_session == NULL);
  ASSERT_TRUE(CallInitiate());
  if (!CallOnInitiateMessage(local_session, candidates)) {
    delete local_session;
    FAIL();
  }
  ASSERT_TRUE(CallConnect());
  ASSERT_FALSE(CallbackReceived(this, 1000));
  ASSERT_TRUE(!CallHasAudioChannel() &&
              CallHasVideoChannel());
}
