// Copyright 2017 The Fuchsia 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 <lib/async/cpp/task.h>
#include <lib/async/cpp/time.h>
#include <zircon/assert.h>

#include <utility>

namespace async {
namespace internal {

struct RetainedTask : public async_task_t {
  RetainedTask(fit::closure handler, zx::time deadline)
      : async_task_t{{ASYNC_STATE_INIT}, &RetainedTask::Handler, deadline.get()},
        handler(static_cast<fit::closure&&>(handler)) {}

  fit::closure handler;

  static void Handler(async_dispatcher_t* dispatcher, async_task_t* task, zx_status_t status) {
    auto self = static_cast<RetainedTask*>(task);
    if (status == ZX_OK)
      self->handler();
    delete self;
  }
};

}  // namespace internal

zx_status_t PostTask(async_dispatcher_t* dispatcher, fit::closure handler) {
  return PostTaskForTime(dispatcher, static_cast<fit::closure&&>(handler), async::Now(dispatcher));
}

zx_status_t PostDelayedTask(async_dispatcher_t* dispatcher, fit::closure handler,
                            zx::duration delay) {
  return PostTaskForTime(dispatcher, static_cast<fit::closure&&>(handler),
                         async::Now(dispatcher) + delay);
}

zx_status_t PostTaskForTime(async_dispatcher_t* dispatcher, fit::closure handler,
                            zx::time deadline) {
  auto* task = new internal::RetainedTask(static_cast<fit::closure&&>(handler), deadline);
  zx_status_t status = async_post_task(dispatcher, task);
  if (status != ZX_OK)
    delete task;
  return status;
}

TaskBase::TaskBase(async_task_handler_t* handler)
    : task_{{ASYNC_STATE_INIT}, handler, ZX_TIME_INFINITE} {}

TaskBase::~TaskBase() {
  if (dispatcher_) {
    // Failure to cancel here may result in a dangling pointer...
    zx_status_t status = async_cancel_task(dispatcher_, &task_);
    ZX_ASSERT_MSG(status == ZX_OK, "status=%d", status);
  }
}

zx_status_t TaskBase::Post(async_dispatcher_t* dispatcher) {
  return PostForTime(dispatcher, async::Now(dispatcher));
}

zx_status_t TaskBase::PostDelayed(async_dispatcher_t* dispatcher, zx::duration delay) {
  return PostForTime(dispatcher, async::Now(dispatcher) + delay);
}

zx_status_t TaskBase::PostForTime(async_dispatcher_t* dispatcher, zx::time deadline) {
  if (dispatcher_)
    return ZX_ERR_ALREADY_EXISTS;

  dispatcher_ = dispatcher;
  task_.deadline = deadline.get();
  zx_status_t status = async_post_task(dispatcher, &task_);
  if (status != ZX_OK) {
    dispatcher_ = nullptr;
  }
  return status;
}

zx_status_t TaskBase::Cancel() {
  if (!dispatcher_)
    return ZX_ERR_NOT_FOUND;

  async_dispatcher_t* dispatcher = dispatcher_;
  dispatcher_ = nullptr;

  zx_status_t status = async_cancel_task(dispatcher, &task_);
  // |dispatcher| is required to be single-threaded, Cancel() is
  // only supposed to be called on |dispatcher|'s thread, and we
  // verified that the task was pending before calling
  // async_cancel_task(). Assuming that |dispatcher| does not yield
  // between removing the task and invoking the task's handler,
  // |task_| must have been pending with |dispatcher|.
  ZX_DEBUG_ASSERT(status != ZX_ERR_NOT_FOUND);
  return status;
}

Task::Task(Handler handler) : TaskBase(&Task::CallHandler), handler_(std::move(handler)) {}

Task::~Task() = default;

void Task::CallHandler(async_dispatcher_t* dispatcher, async_task_t* task, zx_status_t status) {
  auto self = Dispatch<Task>(task);
  self->handler_(dispatcher, self, status);
}

TaskClosure::TaskClosure(fit::closure handler)
    : TaskBase(&TaskClosure::CallHandler), handler_(std::move(handler)) {}

TaskClosure::~TaskClosure() = default;

void TaskClosure::CallHandler(async_dispatcher_t* dispatcher, async_task_t* task,
                              zx_status_t status) {
  auto self = Dispatch<TaskClosure>(task);  // must do this if status is not ok
  if (status == ZX_OK) {
    self->handler_();
  }
}

}  // namespace async
