// Copyright 2013 The Flutter 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 "handle_waiter.h"

#include <lib/async-loop/default.h>

#include "handle.h"
#include "third_party/tonic/converter/dart_converter.h"
#include "third_party/tonic/dart_args.h"
#include "third_party/tonic/dart_binding_macros.h"
#include "third_party/tonic/dart_library_natives.h"
#include "third_party/tonic/dart_message_handler.h"
#include "third_party/tonic/dart_microtask_queue.h"
#include "third_party/tonic/logging/dart_invoke.h"

using tonic::DartInvokeField;
using tonic::DartState;
using tonic::ToDart;

namespace zircon {
namespace dart {

IMPLEMENT_WRAPPERTYPEINFO(zircon, HandleWaiter);

#define FOR_EACH_BINDING(V) V(HandleWaiter, Cancel)

FOR_EACH_BINDING(DART_NATIVE_NO_UI_CHECK_CALLBACK)

void HandleWaiter::RegisterNatives(tonic::DartLibraryNatives* natives) {
  natives->Register({FOR_EACH_BINDING(DART_REGISTER_NATIVE)});
}

fml::RefPtr<HandleWaiter> HandleWaiter::Create(Handle* handle,
                                               zx_signals_t signals,
                                               Dart_Handle callback) {
  return fml::MakeRefCounted<HandleWaiter>(handle, signals, callback);
}

HandleWaiter::HandleWaiter(Handle* handle,
                           zx_signals_t signals,
                           Dart_Handle callback)
    : wait_(this, handle->handle(), signals),
      handle_(handle),
      callback_(DartState::Current(), callback) {
  FML_CHECK(handle_ != nullptr);
  FML_CHECK(handle_->is_valid());

  zx_status_t status = wait_.Begin(async_get_default_dispatcher());
  FML_DCHECK(status == ZX_OK);
}

HandleWaiter::~HandleWaiter() {
  Cancel();
}

void HandleWaiter::Cancel() {
  FML_DCHECK(wait_.is_pending() == !!handle_);
  if (handle_) {
    // Cancel the wait.
    wait_.Cancel();

    // Release this object from the handle and clear handle_.
    handle_->ReleaseWaiter(this);
    handle_ = nullptr;
  }
  FML_DCHECK(!wait_.is_pending());
}

void HandleWaiter::OnWaitComplete(async_dispatcher_t* dispatcher,
                                  async::WaitBase* wait,
                                  zx_status_t status,
                                  const zx_packet_signal_t* signal) {
  FML_DCHECK(handle_);

  FML_DCHECK(!callback_.is_empty());

  // Hold a reference to this object.
  fml::RefPtr<HandleWaiter> ref(this);

  // Remove this waiter from the handle.
  handle_->ReleaseWaiter(this);

  // Clear handle_.
  handle_ = nullptr;

  auto state = callback_.dart_state().lock();
  FML_DCHECK(state);
  DartState::Scope scope(state);

  // Put the closure invocation on the microtask queue.
  Dart_Handle zircon_lib = Dart_LookupLibrary(ToDart("dart:zircon"));
  FML_DCHECK(!tonic::LogIfError(zircon_lib));

  Dart_Handle owc_type =
      Dart_GetClass(zircon_lib, ToDart("_OnWaitCompleteClosure"));
  FML_DCHECK(!tonic::LogIfError(owc_type));

  FML_DCHECK(!callback_.is_empty());
  std::vector<Dart_Handle> owc_args{callback_.Release(), ToDart(status),
                                    ToDart(signal->observed)};
  Dart_Handle owc =
      Dart_New(owc_type, Dart_Null(), owc_args.size(), owc_args.data());
  FML_DCHECK(!tonic::LogIfError(owc));

  Dart_Handle closure = Dart_GetField(owc, ToDart("_closure"));
  FML_DCHECK(!tonic::LogIfError(closure));

  // TODO(issue#tbd): Use tonic::DartMicrotaskQueue::ScheduleMicrotask()
  // instead when tonic::DartState gets a microtask queue field.
  Dart_Handle async_lib = Dart_LookupLibrary(ToDart("dart:async"));
  FML_DCHECK(!tonic::LogIfError(async_lib));
  std::vector<Dart_Handle> sm_args{closure};
  Dart_Handle sm_result = Dart_Invoke(async_lib, ToDart("scheduleMicrotask"),
                                      sm_args.size(), sm_args.data());
  FML_DCHECK(!tonic::LogIfError(sm_result));
}

}  // namespace dart
}  // namespace zircon
