/*
 *  Copyright (c) 2020 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 "test/time_controller/simulated_thread.h"

#include <algorithm>
#include <utility>

#include "rtc_base/task_utils/to_queued_task.h"

namespace webrtc {
namespace {

// A socket server that does nothing. It's different from NullSocketServer in
// that it does allow sleep/wakeup. This avoids usage of an Event instance which
// otherwise would cause issues with the simulated Yeild behavior.
class DummySocketServer : public rtc::SocketServer {
 public:
  rtc::Socket* CreateSocket(int family, int type) override {
    RTC_NOTREACHED();
    return nullptr;
  }
  rtc::AsyncSocket* CreateAsyncSocket(int family, int type) override {
    RTC_NOTREACHED();
    return nullptr;
  }
  bool Wait(int cms, bool process_io) override {
    RTC_CHECK_EQ(cms, 0);
    return true;
  }
  void WakeUp() override {}
};

}  // namespace

SimulatedThread::SimulatedThread(
    sim_time_impl::SimulatedTimeControllerImpl* handler,
    absl::string_view name,
    std::unique_ptr<rtc::SocketServer> socket_server)
    : rtc::Thread(socket_server ? std::move(socket_server)
                                : std::make_unique<DummySocketServer>()),
      handler_(handler),
      name_(new char[name.size()]) {
  std::copy_n(name.begin(), name.size(), name_);
}

SimulatedThread::~SimulatedThread() {
  handler_->Unregister(this);
  delete[] name_;
}

void SimulatedThread::RunReady(Timestamp at_time) {
  CurrentThreadSetter set_current(this);
  ProcessMessages(0);
  int delay_ms = GetDelay();
  rtc::CritScope lock(&lock_);
  if (delay_ms == kForever) {
    next_run_time_ = Timestamp::PlusInfinity();
  } else {
    next_run_time_ = at_time + TimeDelta::ms(delay_ms);
  }
}

void SimulatedThread::Send(const rtc::Location& posted_from,
                           rtc::MessageHandler* phandler,
                           uint32_t id,
                           rtc::MessageData* pdata) {
  if (IsQuitting())
    return;
  rtc::Message msg;
  msg.posted_from = posted_from;
  msg.phandler = phandler;
  msg.message_id = id;
  msg.pdata = pdata;
  if (IsCurrent()) {
    msg.phandler->OnMessage(&msg);
  } else {
    TaskQueueBase* yielding_from = TaskQueueBase::Current();
    handler_->StartYield(yielding_from);
    CurrentThreadSetter set_current(this);
    msg.phandler->OnMessage(&msg);
    handler_->StopYield(yielding_from);
  }
}

void SimulatedThread::Post(const rtc::Location& posted_from,
                           rtc::MessageHandler* phandler,
                           uint32_t id,
                           rtc::MessageData* pdata,
                           bool time_sensitive) {
  rtc::Thread::Post(posted_from, phandler, id, pdata, time_sensitive);
  rtc::CritScope lock(&lock_);
  next_run_time_ = Timestamp::MinusInfinity();
}

void SimulatedThread::PostDelayed(const rtc::Location& posted_from,
                                  int delay_ms,
                                  rtc::MessageHandler* phandler,
                                  uint32_t id,
                                  rtc::MessageData* pdata) {
  rtc::Thread::PostDelayed(posted_from, delay_ms, phandler, id, pdata);
  rtc::CritScope lock(&lock_);
  next_run_time_ =
      std::min(next_run_time_, Timestamp::ms(rtc::TimeMillis() + delay_ms));
}

void SimulatedThread::PostAt(const rtc::Location& posted_from,
                             int64_t target_time_ms,
                             rtc::MessageHandler* phandler,
                             uint32_t id,
                             rtc::MessageData* pdata) {
  rtc::Thread::PostAt(posted_from, target_time_ms, phandler, id, pdata);
  rtc::CritScope lock(&lock_);
  next_run_time_ = std::min(next_run_time_, Timestamp::ms(target_time_ms));
}

void SimulatedThread::Stop() {
  Thread::Quit();
}

SimulatedMainThread::SimulatedMainThread(
    sim_time_impl::SimulatedTimeControllerImpl* handler)
    : SimulatedThread(handler, "main", nullptr), current_setter_(this) {}

SimulatedMainThread::~SimulatedMainThread() {
  // Removes pending tasks in case they keep shared pointer references to
  // objects whose destructor expects to run before the Thread destructor.
  Stop();
  DoDestroy();
}

}  // namespace webrtc
