/*
 * Copyright 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "common/message_loop_thread.h"

#include <sys/syscall.h>
#include <unistd.h>
#include <thread>

#include <base/strings/stringprintf.h>

#include "gd/common/init_flags.h"
#include "osi/include/log.h"

namespace bluetooth {

namespace common {

static constexpr int kRealTimeFifoSchedulingPriority = 1;

MessageLoopThread::MessageLoopThread(const std::string& thread_name)
    : MessageLoopThread(thread_name, false) {}

MessageLoopThread::MessageLoopThread(const std::string& thread_name,
                                     bool is_main)
    : thread_name_(thread_name),
      message_loop_(nullptr),
      run_loop_(nullptr),
      thread_(nullptr),
      thread_id_(-1),
      linux_tid_(-1),
      weak_ptr_factory_(this),
      shutting_down_(false),
      is_main_(is_main),
      rust_thread_(nullptr) {}

MessageLoopThread::~MessageLoopThread() { ShutDown(); }

void MessageLoopThread::StartUp() {
  if (is_main_ && init_flags::gd_rust_is_enabled()) {
    rust_thread_ = new ::rust::Box<shim::rust::MessageLoopThread>(
        shim::rust::main_message_loop_thread_create());
    auto rust_id =
        bluetooth::shim::rust::main_message_loop_thread_start(**rust_thread_);
    thread_id_ = rust_id;
    linux_tid_ = rust_id;
    return;
  }

  std::promise<void> start_up_promise;
  std::future<void> start_up_future = start_up_promise.get_future();
  {
    std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
    if (thread_ != nullptr) {
      LOG(WARNING) << __func__ << ": thread " << *this << " is already started";

      return;
    }
    thread_ = new std::thread(&MessageLoopThread::RunThread, this,
                              std::move(start_up_promise));
  }
  start_up_future.wait();
}

bool MessageLoopThread::DoInThread(const base::Location& from_here,
                                   base::OnceClosure task) {
  return DoInThreadDelayed(from_here, std::move(task), base::TimeDelta());
}

bool MessageLoopThread::DoInThreadDelayed(const base::Location& from_here,
                                          base::OnceClosure task,
                                          const base::TimeDelta& delay) {
  std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
  if (is_main_ && init_flags::gd_rust_is_enabled()) {
    if (rust_thread_ == nullptr) {
      LOG(ERROR) << __func__ << ": rust thread is null for thread " << *this
                 << ", from " << from_here.ToString();
      return false;
    }

    shim::rust::main_message_loop_thread_do_delayed(
        **rust_thread_,
        std::make_unique<shim::rust::OnceClosure>(std::move(task)),
        delay.InMilliseconds());
    return true;
  }

  if (message_loop_ == nullptr) {
    LOG(ERROR) << __func__ << ": message loop is null for thread " << *this
               << ", from " << from_here.ToString();
    return false;
  }
  if (!message_loop_->task_runner()->PostDelayedTask(from_here, std::move(task),
                                                     delay)) {
    LOG(ERROR) << __func__
               << ": failed to post task to message loop for thread " << *this
               << ", from " << from_here.ToString();
    return false;
  }
  return true;
}

void MessageLoopThread::ShutDown() {
  {
    if (is_main_ && init_flags::gd_rust_is_enabled()) {
      delete rust_thread_;
      rust_thread_ = nullptr;
      thread_id_ = -1;
      linux_tid_ = -1;
      return;
    }

    std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
    if (thread_ == nullptr) {
      LOG(INFO) << __func__ << ": thread " << *this << " is already stopped";
      return;
    }
    if (message_loop_ == nullptr) {
      LOG(INFO) << __func__ << ": message_loop_ is null. Already stopping";
      return;
    }
    if (shutting_down_) {
      LOG(INFO) << __func__ << ": waiting for thread to join";
      return;
    }
    shutting_down_ = true;
    CHECK_NE(thread_id_, base::PlatformThread::CurrentId())
        << __func__ << " should not be called on the thread itself. "
        << "Otherwise, deadlock may happen.";
    if (!message_loop_->task_runner()->PostTask(
            FROM_HERE, run_loop_->QuitWhenIdleClosure())) {
      LOG(FATAL) << __func__
                 << ": failed to post task to message loop for thread "
                 << *this;
    }
  }
  thread_->join();
  {
    std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
    delete thread_;
    thread_ = nullptr;
    shutting_down_ = false;
  }
}

base::PlatformThreadId MessageLoopThread::GetThreadId() const {
  std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
  return thread_id_;
}

std::string MessageLoopThread::GetName() const { return thread_name_; }

std::string MessageLoopThread::ToString() const {
  std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
  return base::StringPrintf("%s(%d)", thread_name_.c_str(), thread_id_);
}

bool MessageLoopThread::IsRunning() const {
  std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
  return thread_id_ != -1;
}

// Non API method, should not be protected by API mutex
void MessageLoopThread::RunThread(MessageLoopThread* thread,
                                  std::promise<void> start_up_promise) {
  thread->Run(std::move(start_up_promise));
}

btbase::AbstractMessageLoop* MessageLoopThread::message_loop() const {
  ASSERT_LOG(!is_main_,
             "you are not allowed to get the main thread's message loop");

  std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
  return message_loop_;
}

bool MessageLoopThread::EnableRealTimeScheduling() {
  std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);

  if (!IsRunning()) {
    LOG(ERROR) << __func__ << ": thread " << *this << " is not running";
    return false;
  }

  struct sched_param rt_params = {.sched_priority =
                                      kRealTimeFifoSchedulingPriority};
  int rc = sched_setscheduler(linux_tid_, SCHED_FIFO, &rt_params);
  if (rc != 0) {
    LOG(ERROR) << __func__ << ": unable to set SCHED_FIFO priority "
               << kRealTimeFifoSchedulingPriority << " for linux_tid "
               << std::to_string(linux_tid_) << ", thread " << *this
               << ", error: " << strerror(errno);
    return false;
  }
  return true;
}

base::WeakPtr<MessageLoopThread> MessageLoopThread::GetWeakPtr() {
  std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
  return weak_ptr_factory_.GetWeakPtr();
}

void MessageLoopThread::Run(std::promise<void> start_up_promise) {
  {
    std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
    if (is_main_ && init_flags::gd_rust_is_enabled()) {
      return;
    }

    LOG(INFO) << __func__ << ": message loop starting for thread "
              << thread_name_;
    base::PlatformThread::SetName(thread_name_);
    message_loop_ = new btbase::AbstractMessageLoop();
    run_loop_ = new base::RunLoop();
    thread_id_ = base::PlatformThread::CurrentId();
    linux_tid_ = static_cast<pid_t>(syscall(SYS_gettid));
    start_up_promise.set_value();
  }

  // Blocking until ShutDown() is called
  run_loop_->Run();

  {
    std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
    thread_id_ = -1;
    linux_tid_ = -1;
    delete message_loop_;
    message_loop_ = nullptr;
    delete run_loop_;
    run_loop_ = nullptr;
    LOG(INFO) << __func__ << ": message loop finished for thread "
              << thread_name_;
  }
}

}  // namespace common

}  // namespace bluetooth
