// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "glib-bridge/glib_bridge.h"

#include <utility>

#include <base/threading/sequenced_task_runner_handle.h>

namespace glib_bridge {

namespace {

struct GMainContextLock {
 public:
  explicit GMainContextLock(GMainContext* context) : context_(context) {
    CHECK(context_);
    CHECK(g_main_context_acquire(context_));
  }

  ~GMainContextLock() { g_main_context_release(context_); }

 private:
  GMainContext* context_;  // weak
};

}  // namespace

GlibBridge::GlibBridge()
    : glib_context_(g_main_context_new()),
      state_(State::kPreparingIteration),
      weak_ptr_factory_(this) {
  CHECK(glib_context_);
  g_main_context_push_thread_default(glib_context_);
  base::SequencedTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::Bind(&GlibBridge::PrepareIteration,
                            weak_ptr_factory_.GetWeakPtr()));
}

GlibBridge::~GlibBridge() {
  g_main_context_pop_thread_default(glib_context_);
  g_main_context_unref(glib_context_);
}

void GlibBridge::PrepareIteration() {
  CHECK_EQ(state_, State::kPreparingIteration);
  CHECK(watchers_.empty());
  GMainContextLock _l(glib_context_);

  bool immediate = g_main_context_prepare(glib_context_, &max_priority_);

  int num_fds =
      g_main_context_query(glib_context_, max_priority_, nullptr, nullptr, 0);
  poll_fds_ = std::vector<GPollFD>(num_fds);

  int timeout_ms;
  g_main_context_query(glib_context_, max_priority_, &timeout_ms, &poll_fds_[0],
                       num_fds);
  if (immediate || (num_fds == 0 && timeout_ms == 0)) {
    DVLOG(1) << "Iteration can be dispatched immediately";
    base::SequencedTaskRunnerHandle::Get()->PostTask(
        FROM_HERE,
        base::Bind(&GlibBridge::Dispatch, weak_ptr_factory_.GetWeakPtr()));
    state_ = State::kReadyForDispatch;
    return;
  }

  // Collect information about which poll flags we need for each fd.
  std::map<int, int> poll_flags;
  for (GPollFD& poll_fd : poll_fds_) {
    fd_map_[poll_fd.fd].push_back(&poll_fd);
    poll_flags[poll_fd.fd] |= poll_fd.events;
  }

  DVLOG(1) << "Preparing iteration with timeout " << timeout_ms << " ms, "
           << poll_flags.size() << " event FDs";

  for (const auto& fd_flags : poll_flags) {
    std::unique_ptr<base::FileDescriptorWatcher::Controller> reader;
    if (fd_flags.second & G_IO_IN) {
      reader = base::FileDescriptorWatcher::WatchReadable(
          fd_flags.first,
          base::Bind(&GlibBridge::OnEvent, weak_ptr_factory_.GetWeakPtr(),
                     fd_flags.first, G_IO_IN));
      CHECK(reader) << "Could not set up read watcher for fd "
                    << fd_flags.first;
    }

    std::unique_ptr<base::FileDescriptorWatcher::Controller> writer;
    if (fd_flags.second & G_IO_OUT) {
      writer = base::FileDescriptorWatcher::WatchWritable(
          fd_flags.first,
          base::Bind(&GlibBridge::OnEvent, weak_ptr_factory_.GetWeakPtr(),
                     fd_flags.first, G_IO_OUT));
      CHECK(writer) << "Could not set up write watcher for fd "
                    << fd_flags.first;
    }

    watchers_[fd_flags.first] = Watcher{std::move(reader), std::move(writer)};
  }

  state_ = State::kWaitingForEvents;
  if (timeout_ms < 0)
    return;

  base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(timeout_ms);
  timeout_closure_.Reset(
      base::Bind(&GlibBridge::Timeout, weak_ptr_factory_.GetWeakPtr()));
  base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
      FROM_HERE, timeout_closure_.callback(), timeout);
}

void GlibBridge::OnEvent(int fd, int flag) {
  CHECK(state_ == State::kWaitingForEvents ||
        state_ == State::kReadyForDispatch);
  DVLOG(2) << "OnEvent(" << fd << ", " << flag << ")";
  for (GPollFD* poll_fd : fd_map_[fd])
    poll_fd->revents |= flag & poll_fd->events;

  if (flag & G_IO_IN)
    watchers_[fd].reader.reset();
  if (flag & G_IO_OUT)
    watchers_[fd].writer.reset();

  // Avoid posting the dispatch task if it's already posted
  if (state_ == State::kReadyForDispatch)
    return;

  base::SequencedTaskRunnerHandle::Get()->PostTask(
      FROM_HERE,
      base::Bind(&GlibBridge::Dispatch, weak_ptr_factory_.GetWeakPtr()));
  state_ = State::kReadyForDispatch;
}

void GlibBridge::Timeout() {
  CHECK_EQ(state_, State::kWaitingForEvents);
  base::SequencedTaskRunnerHandle::Get()->PostTask(
      FROM_HERE,
      base::Bind(&GlibBridge::Dispatch, weak_ptr_factory_.GetWeakPtr()));
  state_ = State::kReadyForDispatch;
}

void GlibBridge::Dispatch() {
  CHECK_EQ(state_, State::kReadyForDispatch);
  GMainContextLock _l(glib_context_);

  bool dispatched = g_main_context_check(glib_context_, max_priority_,
                                         poll_fds_.data(), poll_fds_.size());
  g_main_context_dispatch(glib_context_);
  DVLOG(2) << (dispatched ? "Found" : "Did not find") << " source to dispatch";

  timeout_closure_.Cancel();
  watchers_.clear();
  poll_fds_.clear();
  max_priority_ = -1;
  base::SequencedTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::Bind(&GlibBridge::PrepareIteration,
                            weak_ptr_factory_.GetWeakPtr()));
  state_ = State::kPreparingIteration;
}

}  // namespace glib_bridge
