/*
 * 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/fakesession.h"
#include "talk/p2p/base/portallocator.h"
#include "talk/p2p/base/sessiondescription.h"
#include "talk/p2p/client/fakeportallocator.h"
#include "talk/session/phone/mediasessionclient.h"

class WebRtcSessionTest
    : public sigslot::has_slots<>,
      public testing::Test {
 public:
  enum CallbackId {
    kNone,
    kOnAddStream,
    kOnRemoveStream,
    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 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_->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;
    }
    return true;
  }

  bool CallCreateVideoChannel(const std::string& stream_id) {
    if (!session_->CreateVideoChannel(stream_id)) {
      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());
}
