// Copyright 2018 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 "vsync_waiter.h"

#include <trace/event.h>

#include "topaz/lib/deprecated_loop/message_loop.h"
#include "vsync_recorder.h"

namespace flutter {

VsyncWaiter::VsyncWaiter(std::string debug_label,
                         zx_handle_t session_present_handle,
                         blink::TaskRunners task_runners)
    : shell::VsyncWaiter(task_runners),
      debug_label_(std::move(debug_label)),
      session_wait_(session_present_handle, SessionPresentSignal),
      weak_factory_(this) {
  auto wait_handler = [&](async_dispatcher_t* dispatcher,   //
                          async::Wait* wait,                //
                          zx_status_t status,               //
                          const zx_packet_signal_t* signal  //
                      ) {
    if (status != ZX_OK) {
      FML_LOG(ERROR) << "Vsync wait failed.";
      return;
    }

    wait->Cancel();

    FireCallbackNow();
  };

  session_wait_.set_handler(wait_handler);
}

VsyncWaiter::~VsyncWaiter() { session_wait_.Cancel(); }

static fml::TimePoint SnapToNextPhase(fml::TimePoint value,
                                      fml::TimePoint phase,
                                      fml::TimeDelta interval) {
  fml::TimeDelta offset = (phase - value) % interval;
  if (offset < fml::TimeDelta::Zero()) {
    offset = offset + interval;
  }
  return value + offset;
}

void VsyncWaiter::AwaitVSync() {
  VsyncInfo vsync_info = VsyncRecorder::GetInstance().GetCurrentVsyncInfo();

  fml::TimePoint now = fml::TimePoint::Now();
  fml::TimePoint next_vsync = SnapToNextPhase(now, vsync_info.presentation_time,
                                              vsync_info.presentation_interval);
  task_runners_.GetUITaskRunner()->PostDelayedTask(
      [self = weak_factory_.GetWeakPtr()] {
        if (self) {
          self->FireCallbackWhenSessionAvailable();
        }
      },
      next_vsync - now);
}

void VsyncWaiter::FireCallbackWhenSessionAvailable() {
  TRACE_DURATION("flutter", "VsyncWaiter::FireCallbackWhenSessionAvailable");
  FML_DCHECK(task_runners_.GetUITaskRunner()->RunsTasksOnCurrentThread());
  if (session_wait_.Begin(
          deprecated_loop::MessageLoop::GetCurrent()->dispatcher()) != ZX_OK) {
    FML_LOG(ERROR) << "Could not begin wait for Vsync.";
  }
}

void VsyncWaiter::FireCallbackNow() {
  FML_DCHECK(task_runners_.GetUITaskRunner()->RunsTasksOnCurrentThread());

  VsyncInfo vsync_info = VsyncRecorder::GetInstance().GetCurrentVsyncInfo();

  fml::TimePoint now = fml::TimePoint::Now();
  fml::TimePoint next_vsync = SnapToNextPhase(now, vsync_info.presentation_time,
                                              vsync_info.presentation_interval);
  fml::TimePoint previous_vsync = next_vsync - vsync_info.presentation_interval;

  FireCallback(previous_vsync, next_vsync);
}

}  // namespace flutter
