/*
 * Copyright 2024 Rive
 */

// Don't compile this file as part of the "tests" project.
#ifndef TESTING

#include "player.hpp"

#include <optional>
#include <sstream>
#include "common/test_harness.hpp"
#include "common/testing_window.hpp"
#include "rive/animation/state_machine_instance.hpp"
#include "rive/artboard.hpp"
#include "rive/file.hpp"
#include "rive/input/gamepad_batch.hpp"
#include "rive/renderer.hpp"
#include "rive/renderer/render_context.hpp"
#include "rive/renderer/scoped_autorelease_pool.hpp"
#include "rive/scene.hpp"
#include "rive/text/font_hb.hpp"
#include "rive/text/raw_text.hpp"
#include "rive/viewmodel/viewmodel_instance.hpp"
#ifdef WITH_RIVE_SCRIPTING_LUAU
#include "rive/lua/rive_lua_libs.hpp"
#include "rive/lua/scripting_vm.hpp"
#endif
#ifdef RIVE_CANVAS
#include "common/testing_window_sink.hpp"
#include "rive/renderer/cmd/deferred_session.hpp"
#endif
#include "assets/roboto_flex.ttf.hpp"
#include <stdio.h>
#include <condition_variable>
#include <fstream>
#include <mutex>
#include <optional>
#include <thread>

#if defined(RIVE_ANDROID) && !defined(RIVE_UNREAL)
#include "common/rive_android_app.hpp"
#endif

#if (defined(RIVE_IOS) || defined(RIVE_IOS_SIMULATOR)) && !defined(RIVE_UNREAL)
#include "common/rive_ios_app.hpp"
#endif

#ifdef __EMSCRIPTEN__
#include "common/rive_wasm_app.hpp"
#include <emscripten/emscripten.h>
#include <emscripten/html5.h>
#endif

// The FPS readout drawn over the .riv, and the resources it needs.
struct Player::FPSOverlay
{
  rive::rcp<rive::Font> roboto;
  rive::rcp<rive::RenderPaint> blackStroke;
  rive::rcp<rive::RenderPaint> whiteFill;
  std::unique_ptr<rive::RawText> text;
  int frames = 0;
  std::chrono::high_resolution_clock::time_point timeLastUpdate;
};

struct Player::FrameJob
{
  TestingWindow::FrameOptions options;
#ifdef RIVE_CANVAS
  rive::cmd::DeferredFrame frame;
#endif
  std::vector<uint8_t>* pixels = nullptr;
};

// One frame in flight at most: submit blocks until the previous frame has
// presented. Every window call happens on this thread while it lives.
struct Player::RenderThread
{
  explicit RenderThread(Player* player)
      : m_thread([this, player] { run(player); })
  {}

  ~RenderThread()
  {
    {
      std::lock_guard lock(m_mutex);
      m_quit = true;
    }
    m_cv.notify_all();
    m_thread.join();
  }

  void submit(FrameJob job)
  {
    std::unique_lock lock(m_mutex);
    m_cv.wait(lock, [this] { return idle(); });
    m_pending = std::move(job);
    m_cv.notify_all();
  }

  // Returns once every submitted frame has presented.
  void drain()
  {
    std::unique_lock lock(m_mutex);
    m_cv.wait(lock, [this] { return idle(); });
  }

private:
  bool idle() const { return !m_pending.has_value(); }

  void run(Player* player)
  {
    for (;;)
    {
      std::unique_lock lock(m_mutex);
      m_cv.wait(lock, [this] { return m_pending.has_value() || m_quit; });
      if (!m_pending.has_value())
      {
        return;
      }
      lock.unlock();
      {
        rive::gpu::ScopedAutoreleasePool autoreleasePool;
        player->presentFrame(*m_pending);
      }
      lock.lock();
      m_pending.reset();
      lock.unlock();
      m_cv.notify_all();
    }
  }

  std::mutex m_mutex;
  std::condition_variable m_cv;
  std::optional<FrameJob> m_pending;
  bool m_quit = false;
  std::thread m_thread; // last, so the state above exists before it runs
};

Player::Player() : m_fps(std::make_unique<FPSOverlay>()) {}

// Joins before the replay state below goes, for hosts that skip shutdown.
Player::~Player() { m_renderThread = nullptr; }

void Player::shutdown()
{
  m_renderThread = nullptr;
#ifdef RIVE_CANVAS
  if (m_session != nullptr)
  {
    // Session made resources unwind through the session and the resident
    // tables against the live context, not at exit.
    m_fps.reset();
    m_scene = nullptr;
    m_artboard = nullptr;
    m_viewModelInstance = nullptr;
    m_file = nullptr;
    m_session = nullptr;
    m_replayer = nullptr;
  }
#endif
}

static void update_parameter(int& val, int multiplier, char key, bool seenBang)
{
  if (seenBang)
    val = multiplier;
  else if (key >= 'a')
    val += multiplier;
  else
    val -= multiplier;
}

void Player::keyPressed(char key)
{
  if (key >= '0' && key <= '9')
  {
    m_keyMultiplier = m_keyMultiplier * 10 + (key - '0');
    m_seenDigit = true;
    return;
  }
  if (key == '!')
  {
    m_seenBang = true;
    return;
  }
  if (!m_seenDigit)
  {
    m_keyMultiplier = m_seenBang ? 0 : 1;
  }
  switch (key)
  {
    case 'h':
    case 'H':
      update_parameter(m_copiesLeft, m_keyMultiplier, key, m_seenBang);
      break;
    case 'k':
    case 'K':
      update_parameter(m_copiesAbove, m_keyMultiplier, key, m_seenBang);
      break;
    case 'l':
    case 'L':
      update_parameter(m_copiesRight, m_keyMultiplier, key, m_seenBang);
      break;
    case 'j':
    case 'J':
      update_parameter(m_copiesBelow, m_keyMultiplier, key, m_seenBang);
      break;
    case 'x':
    case 'X':
      update_parameter(m_copiesLeft, m_keyMultiplier, key, m_seenBang);
      update_parameter(m_copiesRight, m_keyMultiplier, key, m_seenBang);
      break;
    case 'y':
    case 'Y':
      update_parameter(m_copiesAbove, m_keyMultiplier, key, m_seenBang);
      update_parameter(m_copiesBelow, m_keyMultiplier, key, m_seenBang);
      break;
    case 'r':
    case 'R':
      update_parameter(m_rotations90, m_keyMultiplier, key, m_seenBang);
      break;
    case 'z':
    case 'Z':
      update_parameter(m_zoomLevel, m_keyMultiplier, key, m_seenBang);
      break;
    case 's':
    case 'S':
      update_parameter(m_spacing, m_keyMultiplier, key, m_seenBang);
      break;
    case 'm':
      m_monitorIdx += m_keyMultiplier;
      break;
    case 'p':
      m_paintStyle = (m_paintStyle + m_keyMultiplier) % 3;
      break;
    case 'P':
      m_paintStyle = (m_paintStyle + 3 - (m_keyMultiplier % 3)) % 3;
      break;
    case 'w':
      m_wireframe = !m_wireframe;
      break;
    case 'u':
      m_paused = !m_paused;
      break;
    case 'f':
      m_forceFixedDeltaTime = !m_forceFixedDeltaTime;
      break;
    case 'q':
    case '\x03': // ^C
      m_quit = true;
      break;
    case '\x1b': // Esc
      break;
    case '`':
      m_hotloadShaders = true;
      break;
    case '~':
      if (m_inputMode == InputMode::chars)
      {
        m_inputMode = InputMode::consolecommands;
      }
      else
      {
        m_inputMode = InputMode::chars;
      }
      break;
    default:
      // fprintf(stderr, "invalid option: %c\n", key);
      // abort();
      break;
  }
  m_keyMultiplier = 0;
  m_seenDigit = false;
  m_seenBang = false;
}

bool Player::parseArgs(
    int argc,
    const char* const argv[],
    FrameRunner::LaunchOptions& options)
{
  bool onlyUbershaders = false;
  // Applied after parsing, since --backend resets the backend params.
  std::optional<TestingWindow::BackendParams::PresentMode> presentMode;
  std::optional<TestingWindow::BackendParams::Refresh> refresh;

  for (int i = 1; i < argc; ++i)
  {
    if (strcmp(argv[i], "--test_harness") == 0)
    {
      TestHarness::Instance().init(TCPClient::Connect(argv[++i]), 0);
      if (!TestHarness::Instance().fetchRivFile(m_rivName, m_pendingRivBytes))
      {
        fprintf(stderr, "failed to fetch a riv file.");
        abort();
      }
    }
    else if (strcmp(argv[i], "--backend") == 0 || strcmp(argv[i], "-b") == 0)
    {
      options.backend = TestingWindow::ParseBackend(
          argv[++i],
          &options.backendParams);
    }
    else if (argv[i][0] == '-' && argv[i][1] == 'b') // "-bvk" without a space.
    {
      options.backend = TestingWindow::ParseBackend(
          argv[i] + 2,
          &options.backendParams);
    }
    else if (strcmp(argv[i], "--options") == 0 || strcmp(argv[i], "-k") == 0)
    {
      for (const char* k = argv[++i]; *k; ++k)
      {
        keyPressed(*k);
      }
    }
    else if (
        strcmp(argv[i], "--only_ubershaders") == 0 ||
        strcmp(argv[i], "-u") == 0)
    {
      onlyUbershaders = true;
    }
    else if (strcmp(argv[i], "--deferred") == 0)
    {
      m_useDeferred = true;
    }
    else if (strcmp(argv[i], "--fit") == 0 && i + 1 < argc)
    {
      const char* fit = argv[++i];
      m_fitSet = true;
      m_fit = strcmp(fit, "layout") == 0  ? rive::Fit::layout
              : strcmp(fit, "cover") == 0 ? rive::Fit::cover
              : strcmp(fit, "fill") == 0  ? rive::Fit::fill
                                          : rive::Fit::contain;
    }
    else if (strcmp(argv[i], "--refresh") == 0 && i + 1 < argc)
    {
      using RR = TestingWindow::BackendParams::Refresh;
      const char* rate = argv[++i];
      if (strcmp(rate, "60") == 0)
      {
        refresh = RR::fixed60;
      }
      else if (strcmp(rate, "120") == 0)
      {
        refresh = RR::fixed120;
      }
      else if (strcmp(rate, "vrr") == 0)
      {
        refresh = RR::variable;
      }
      else
      {
        fprintf(stderr, "--refresh must be 60, 120 or vrr, not %s\n", rate);
        abort();
      }
    }
    else if (strcmp(argv[i], "--present") == 0 && i + 1 < argc)
    {
      using PM = TestingWindow::BackendParams::PresentMode;
      const char* mode = argv[++i];
      if (strcmp(mode, "fifo") == 0)
      {
        presentMode = PM::fifo;
      }
      else if (strcmp(mode, "relaxed") == 0)
      {
        presentMode = PM::fifoRelaxed;
      }
      else if (strcmp(mode, "mailbox") == 0)
      {
        presentMode = PM::mailbox;
      }
      else if (strcmp(mode, "immediate") == 0)
      {
        presentMode = PM::immediate;
      }
      else
      {
        fprintf(
            stderr,
            "--present must be fifo, relaxed, mailbox or "
            "immediate, not %s\n",
            mode);
        abort();
      }
    }
    else if (strcmp(argv[i], "--threaded") == 0)
    {
      m_threaded = true;
    }
    else if (strcmp(argv[i], "--gpu-profile") == 0)
    {
      m_gpuProfile = true;
    }
    else if (strcmp(argv[i], "--dump") == 0 && i + 1 < argc)
    {
      m_dumpPath = argv[++i];
    }
    else if (strcmp(argv[i], "--dump-frame") == 0 && i + 1 < argc)
    {
      m_dumpFrame = atoi(argv[++i]);
    }
    else if (argv[i][0] == '-' && argv[i][1] == 'k') // "-k1234asdf" without a
                                                     // space.
    {
      for (const char* k = argv[i] + 2; *k; ++k)
      {
        keyPressed(*k);
      }
    }
    else if (strcmp(argv[i], "--window") == 0 || strcmp(argv[i], "-w") == 0)
    {
      options.visibility = TestingWindow::Visibility::window;
    }
    else
    {
      // No argument name defaults to the source riv.
      if (strcmp(argv[i], "--src") == 0 || strcmp(argv[i], "-s") == 0)
      {
        ++i;
      }
      m_rivName = argv[i];
      std::ifstream rivStream(m_rivName, std::ios::binary);
      m_pendingRivBytes = std::vector<uint8_t>(
          std::istreambuf_iterator<char>(rivStream),
          {});
    }
  }

  if (presentMode)
  {
    options.backendParams.presentMode = *presentMode;
  }
  if (refresh)
  {
    options.backendParams.refresh = *refresh;
  }
  if (onlyUbershaders)
  {
    options.backendParams.shaderCompilationMode = rive::gpu::
        ShaderCompilationMode::onlyUbershaders;
  }

  return !m_pendingRivBytes.empty();
}

void Player::init()
{
  init(std::move(m_rivName), std::move(m_pendingRivBytes));
}

void Player::init(std::string rivName, std::vector<uint8_t> rivBytes)
{
  m_rivName = std::move(rivName);
  m_factory = TestingWindow::Get()->factory();
#ifdef RIVE_CANVAS
  if (m_gpuProfile)
  {
    if (auto* rc = TestingWindow::Get()->renderContext())
    {
      if (auto* ore = rc->getOreContext())
      {
        ore->setGpuProfiling(true);
      }
    }
  }
  // Importing through the DeferredSession makes the artboard's own 2D
  // resources deferred objects with ids so drawInternal can record.
  if (m_useDeferred)
  {
    if (auto* rc = TestingWindow::Get()->renderContext())
    {
      if (auto* ore = rc->getOreContext())
      {
        m_session = std::make_unique<rive::cmd::DeferredSession>(
            rive::ore::ReplayCaps::from(*ore));
        // Bound before import so registration scripts that reach for
        // the device find it, like a real host.
        m_session->bindRenderContext(rc);
        declareTarget();
        m_replayer = std::make_unique<rive::cmd::DeferredReplayer>();
        m_factory = m_session.get();
      }
    }
    if (m_session == nullptr)
    {
      printf("--deferred unavailable on this backend, drawing "
             "immediate\n");
    }
    else if (m_threaded && TestingWindow::Get()->supportsRenderThread())
    {
      m_renderThread = std::make_unique<RenderThread>(this);
    }
  }
#else
  if (m_useDeferred)
  {
    printf("--deferred requires a RIVE_CANVAS build, drawing immediate\n");
  }
#endif
  if (m_threaded && m_renderThread == nullptr)
  {
    printf("--threaded needs deferred replay on a window that presents "
           "off the main thread, presenting inline\n");
  }
  m_file = rive::File::import(rivBytes, m_factory);
  assert(m_file);
#if defined(__EMSCRIPTEN__) && defined(WITH_RIVE_SCRIPTING_WASM)
  m_file->startScripts();
#endif

  m_artboard = m_file->artboardDefault();
  assert(m_artboard);
  // A layout artboard is authored to resize, so it fills the window like
  // our other hosts rather than letterboxing at its design size.
  if (!m_fitSet && m_artboard->style() != nullptr)
  {
    m_fit = rive::Fit::layout;
  }

  // Bind the artboard's default view model instance, if it has one, the same
  // way a real host runtime would.
  m_viewModelInstance = m_file->createDefaultViewModelInstance(
      m_artboard.get());
  if (m_viewModelInstance != nullptr)
  {
    m_artboard->bindViewModelInstance(m_viewModelInstance);
  }

  auto stateMachine = m_artboard->defaultStateMachine();
  if (!stateMachine && m_artboard->stateMachineCount() > 0)
  {
    stateMachine = m_artboard->stateMachineAt(0);
  }
  m_stateMachine = stateMachine.get();
  m_scene = std::move(stateMachine);
  if (!m_scene)
  {
    m_scene = m_artboard->animationAt(0);
  }
  assert(m_scene);
  if (m_viewModelInstance != nullptr)
  {
    m_scene->bindViewModelInstance(m_viewModelInstance);
  }

  // Setup FPS.
  m_fps->roboto = HBFont::Decode(assets::roboto_flex_ttf());
  m_fps->blackStroke = m_factory->makeRenderPaint();
  m_fps->blackStroke->color(0xff000000);
  m_fps->blackStroke->style(rive::RenderPaintStyle::stroke);
  m_fps->blackStroke->thickness(4);
  m_fps->whiteFill = m_factory->makeRenderPaint();
  m_fps->whiteFill->color(0xffffffff);
  m_fps->timeLastUpdate = std::chrono::high_resolution_clock::now();
  m_timestampPrevFrame = std::chrono::high_resolution_clock::now();
}

// The state machine takes gamepads as the wire batch our js embedder sends.
static void appendU32(std::vector<uint8_t>& buffer, uint32_t value)
{
  for (int i = 0; i < 4; ++i)
  {
    buffer.push_back(static_cast<uint8_t>(value >> (8 * i)));
  }
}

void Player::submitGamepad(const TestingWindow::InputEventData& event)
{
  if (m_stateMachine == nullptr)
  {
    return;
  }
  const auto& pad = event.metadata.pad;
  std::vector<uint8_t> buffer;
  appendU32(buffer, rive::kGamepadBatchWireVersion);
  if (event.eventType == TestingWindow::InputEvent::GamepadConnected)
  {
    buffer.push_back(static_cast<uint8_t>(rive::GamepadRecordType::connected));
    appendU32(buffer, pad.deviceId);
    buffer.push_back(0); // standard mapping
    buffer.push_back(pad.buttonCount);
    buffer.push_back(pad.axisCount);
    buffer.push_back(0); // padding
    for (int i = 0; i < pad.buttonCount + pad.axisCount; ++i)
    {
      appendU32(buffer, 0); // every value at rest
    }
  }
  else if (event.eventType == TestingWindow::InputEvent::GamepadDisconnected)
  {
    buffer.push_back(
        static_cast<uint8_t>(rive::GamepadRecordType::disconnected));
    appendU32(buffer, pad.deviceId);
  }
  else
  {
    buffer.push_back(static_cast<uint8_t>(rive::GamepadRecordType::update));
    appendU32(buffer, pad.deviceId);
    buffer.push_back(1); // one change
    buffer.push_back(pad.isAxis ? 1 : 0);
    buffer.push_back(pad.index);
    uint32_t bits;
    memcpy(&bits, &pad.value, sizeof(bits));
    appendU32(buffer, bits);
  }
  m_stateMachine->submitGamepadsFromBuffer(buffer.data(), buffer.size());
}

#ifdef RIVE_CANVAS
void Player::declareTarget()
{
  TestingWindow* window = TestingWindow::Get();
  TestingWindow::OreTarget target = window->oreTarget();
  m_session->oreContext().setTarget(
      target.exposed ? rive::ore::Context::TargetDesc::color8(
                           window->width(),
                           window->height(),
                           target.bgra)
                     : rive::ore::Context::TargetDesc{});
}
#endif

void Player::presentFrame(FrameJob& job)
{
#ifdef RIVE_CANVAS
  if (m_session != nullptr)
  {
    TestingWindowFrameSink sink(job.options);
    m_replayer->replayFrame(job.frame, sink);
    uint32_t dropped = m_replayer->droppedDraws();
    if (dropped != 0 && dropped != m_lastDroppedDraws)
    {
      printf("deferred replay dropped %u draws\n", dropped);
    }
    m_lastDroppedDraws = dropped;
  }
#endif
  TestingWindow::Get()->endFrame(job.pixels);
}

bool Player::doFrame()
{
  if (m_quit || TestingWindow::Get()->shouldQuit()
#if defined(RIVE_ANDROID) && !defined(RIVE_UNREAL)
      || !rive_android_app_poll_once()
#endif
  )
  {
    m_quit = true;
    return false;
  }

#ifdef __EMSCRIPTEN__
  {
    // Fit the canvas to the browser window size.
    int windowWidth = EM_ASM_INT(return window["innerWidth"]);
    int windowHeight = EM_ASM_INT(return window["innerHeight"]);
    double devicePixelRatio = emscripten_get_device_pixel_ratio();
    int canvasExpectedWidth = windowWidth * devicePixelRatio;
    int canvasExpectedHeight = windowHeight * devicePixelRatio;
    if (TestingWindow::Get()->width() != canvasExpectedWidth ||
        TestingWindow::Get()->height() != canvasExpectedHeight)
    {
      printf(
          "Resizing HTML canvas to %i x %i.\n",
          canvasExpectedWidth,
          canvasExpectedHeight);
      if (m_renderThread != nullptr)
      {
        m_renderThread->drain();
      }
      TestingWindow::Get()->resize(canvasExpectedWidth, canvasExpectedHeight);
      emscripten_set_element_css_size("#canvas", windowWidth, windowHeight);
    }
  }
#endif

  std::chrono::time_point timeNow = std::chrono::high_resolution_clock::now();
  const double elapsedS = std::chrono::duration_cast<std::chrono::nanoseconds>(
                              timeNow - m_timestampPrevFrame)
                              .count() /
                          1e9; // convert to s
  m_timestampPrevFrame = timeNow;

  float advanceDeltaTime = static_cast<float>(elapsedS);
  if (m_forceFixedDeltaTime)
  {
    advanceDeltaTime = 1.0f / 120;
  }

#ifdef WITH_RIVE_SCRIPTING_WASM
  // Scavenges the script nursery, which otherwise grows until it traps.
  if (const char* warning = m_file->frameBoundary())
  {
    fprintf(stderr, "%s\n", warning);
  }
#endif
  m_scene->advanceAndApply(m_paused ? 0 : advanceDeltaTime);

  m_copiesLeft = std::max(m_copiesLeft, 0);
  m_copiesAbove = std::max(m_copiesAbove, 0);
  m_copiesRight = std::max(m_copiesRight, 0);
  m_copiesBelow = std::max(m_copiesBelow, 0);
  int copyCount = (m_copiesLeft + 1 + m_copiesRight) *
                  (m_copiesAbove + 1 + m_copiesBelow);
  if (copyCount != m_lastReportedCopyCount ||
      m_paused != m_lastReportedPauseState)
  {
    printf(
        "Drawing %i copies of %s%s at %u x %u\n",
        copyCount,
        m_rivName.c_str(),
        m_paused ? " (paused)" : "",
        TestingWindow::Get()->width(),
        TestingWindow::Get()->height());
    m_lastReportedCopyCount = copyCount;
    m_lastReportedPauseState = m_paused;
  }

  const TestingWindow::FrameOptions frameOptions = {
      .clearColor = 0xff303030,
      .doClear = true,
      .wireframe = m_wireframe,
      .fillsDisabled = m_paintStyle == 2,
      .strokesDisabled = m_paintStyle == 1,
  };
  std::unique_ptr<rive::Renderer> renderer;
#ifdef RIVE_CANVAS
  if (m_session != nullptr)
  {
    declareTarget();
    m_session->recordOreReplayMarker();
    renderer = m_session->makeScreenRenderer();
  }
  else
#endif
  {
    renderer = TestingWindow::Get()->beginFrame(frameOptions);
  }

  if (m_hotloadShaders)
  {
    m_hotloadShaders = false;
#ifndef RIVE_NO_STD_SYSTEM
    std::system("sh rebuild_shaders.sh /tmp/rive");
    if (m_renderThread != nullptr)
    {
      m_renderThread->drain();
    }
    TestingWindow::Get()->hotloadShaders();
#endif
  }

  renderer->save();

  uint32_t width = TestingWindow::Get()->width();
  uint32_t height = TestingWindow::Get()->height();
  for (int i = m_rotations90; (i & 3) != 0; --i)
  {
    renderer->transform(rive::Mat2D(0, 1, -1, 0, width, 0));
    std::swap(height, width);
  }
  if (m_fit == rive::Fit::layout &&
      (m_artboard->width() != width || m_artboard->height() != height))
  {
    m_artboard->width(width);
    m_artboard->height(height);
    m_artboard->advance(0.0f);
  }
  if (m_zoomLevel != 0)
  {
    float scale = powf(1.25f, m_zoomLevel);
    renderer->translate(width / 2.f, height / 2.f);
    renderer->scale(scale, scale);
    renderer->translate(width / -2.f, height / -2.f);
  }

  // Draw the .riv.
  renderer->save();
  renderer->align(
      m_fit,
      rive::Alignment::center,
      rive::AABB(0, 0, width, height),
      m_artboard->bounds());
  float spacingPx = m_spacing * 5 + 150;
  renderer->translate(-spacingPx * m_copiesLeft, -spacingPx * m_copiesAbove);
  for (int y = -m_copiesAbove; y <= m_copiesBelow; ++y)
  {
    renderer->save();
    for (int x = -m_copiesLeft; x <= m_copiesRight; ++x)
    {
      m_artboard->drawInternal(renderer.get());
      renderer->translate(spacingPx, 0);
    }
    renderer->restore();
    renderer->translate(0, spacingPx);
  }
  renderer->restore();

  if (m_fps->text != nullptr)
  {
    // Draw FPS.
    renderer->save();
    renderer->translate(0, 20);
    m_fps->text->render(renderer.get(), m_fps->blackStroke);
    m_fps->text->render(renderer.get(), m_fps->whiteFill);
    renderer->restore();
  }

  renderer->restore();

  std::vector<uint8_t> pixels;
  const bool dump = !m_dumpPath.empty() && ++m_frameCounter >= m_dumpFrame;
  FrameJob job = {.options = frameOptions, .pixels = dump ? &pixels : nullptr};
#ifdef RIVE_CANVAS
  if (m_session != nullptr)
  {
    // Snapshot replay is the same path a threaded consumer takes.
    job.frame = rive::cmd::snapshotFrame(*m_session);
    m_session->resetFrame();
  }
#endif
  if (m_renderThread != nullptr)
  {
    m_renderThread->submit(std::move(job));
    if (dump)
    {
      m_renderThread->drain();
    }
  }
  else
  {
    presentFrame(job);
  }
  if (dump)
  {
    uint32_t w = TestingWindow::Get()->width();
    uint32_t h = TestingWindow::Get()->height();
    if (FILE* f = fopen(m_dumpPath.c_str(), "wb"))
    {
      fwrite(&w, sizeof(w), 1, f);
      fwrite(&h, sizeof(h), 1, f);
      fwrite(pixels.data(), 1, pixels.size(), f);
      fclose(f);
      printf(
          "dumped %ux%u frame (%zu bytes) to %s\n",
          w,
          h,
          pixels.size(),
          m_dumpPath.c_str());
    }
    else
    {
      fprintf(stderr, "could not open dump path %s\n", m_dumpPath.c_str());
    }
    m_quit = true;
    return false;
  }

  // Count FPS.
  ++m_fps->frames;
  const double
      elapsedFPSUpdate = std::chrono::duration_cast<std::chrono::nanoseconds>(
                             timeNow - m_fps->timeLastUpdate)
                             .count() /
                         1e9; // convert to s
  if (elapsedFPSUpdate >= 2.0)
  {
    double fps = m_fps->frames / elapsedFPSUpdate;
    if (m_inputMode == InputMode::chars)
    {
      printf("[%.3f FPS]\n", fps);
    }

    char fpsRawText[32];
    snprintf(fpsRawText, sizeof(fpsRawText), "   %.1f FPS   ", fps);
    m_fps->text = std::make_unique<rive::RawText>(m_factory);
    m_fps->text->maxWidth(width);
#ifdef RIVE_ANDROID
    m_fps->text->align(rive::TextAlign::center);
#else
    m_fps->text->align(rive::TextAlign::right);
#endif
    m_fps->text->sizing(rive::TextSizing::fixed);
    m_fps->text->append(fpsRawText, nullptr, m_fps->roboto, 50.f);

    m_fps->frames = 0;
    m_fps->timeLastUpdate = timeNow;
  }

  const rive::Mat2D alignmentMat = computeAlignment(
      m_fit,
      rive::Alignment::center,
      rive::AABB(0, 0, width, height),
      m_artboard->bounds());

  // Consume all input events until none are left in the queue
  TestingWindow::InputEventData inputEventData;
  while (TestingWindow::Get()->consumeInputEvent(inputEventData))
  {
    // Only pointer events carry a position in the union.
    auto alignedPos = [&]() {
      return alignmentMat.invertOrIdentity() *
             rive::Vec2D(
                 inputEventData.metadata.posX,
                 inputEventData.metadata.posY);
    };
    switch (inputEventData.eventType)
    {
      case TestingWindow::InputEvent::KeyPress:
        keyPressed(inputEventData.metadata.key);
        break;

      case TestingWindow::InputEvent::MouseMove:
        m_scene->pointerMove(alignedPos());
        break;

      case TestingWindow::InputEvent::MouseDown:
        m_scene->pointerDown(alignedPos());
        break;

      case TestingWindow::InputEvent::MouseUp:
        m_scene->pointerUp(alignedPos());
        break;
      case TestingWindow::InputEvent::GamepadConnected:
      case TestingWindow::InputEvent::GamepadDisconnected:
      case TestingWindow::InputEvent::GamepadChange:
        submitGamepad(inputEventData);
        break;
    }
  }

  std::string command;
  char key;

  if (m_inputMode == InputMode::consolecommands)
  {
    while (TestHarness::Instance().peekChar(key))
    {
      command += key;
    }

    std::istringstream iss(command);
    std::string first, second;
    iss >> first >> second;
    if (first == "~")
    {
      m_inputMode = InputMode::chars;
    }
    else if (first == "fire")
    {
      if (!second.empty())
      {
        if (auto* trigger = m_scene->getTrigger(second.c_str()))
        {
          trigger->fire();
        }
      }
    }
  }
  else
  {
    while (TestHarness::Instance().peekChar(key))
    {
      keyPressed(key);
    }
  }

  return true;
}

// Unreal owns the main loop: it creates its own Player, parses the same
// arguments through Player::parseArgs(), and pumps doFrame() once per engine
// tick. Everything below (the global player, the shutdown, and main() itself)
// is only for the standalone tool.
#ifndef RIVE_UNREAL

static Player player;

static void player_shutdown()
{
  printf("\nShutting down\n");
  player.shutdown();
  TestingWindow::Destroy(); // Exercise our PLS teardown process now
                            // that we're done.
  TestHarness::Instance().shutdown();
#ifdef __EMSCRIPTEN__
  emscripten_cancel_main_loop();
  EM_ASM(if (window && window.close) window.close(););
#else
  exit(0);
#endif
}

#if defined(RIVE_IOS) || defined(RIVE_IOS_SIMULATOR)
int player_ios_main(int argc, const char* argv[])
#elif defined(RIVE_ANDROID)
int rive_android_main(int argc, const char* const* argv)
#elif defined(__EMSCRIPTEN__)
int rive_wasm_main(int argc, const char* const* argv)
#elif defined(EXTERN_TOOLS)
int rive_main(int argc, const char* argv[])
#else
int main(int argc, const char* argv[])
#endif
{
#ifdef _WIN32
  // Cause stdout and stderr to print immediately without buffering.
  setvbuf(stdout, NULL, _IONBF, 0);
  setvbuf(stderr, NULL, _IONBF, 0);
#endif

  FrameRunner::LaunchOptions options;
  const bool haveRiv = player.parseArgs(argc, argv, options);

  TestingWindow::Init(
      options.backend,
      options.backendParams,
      options.visibility,
#ifdef RIVE_ANDROID
      rive_android_app_wait_for_window()
#elif defined(RIVE_IOS) || defined(RIVE_IOS_SIMULATOR)
      rive_ios_app_wait_for_window()
#else
      reinterpret_cast<void*>(static_cast<intptr_t>(player.monitorIdx()))
#endif
  );

  if (!haveRiv)
  {
    fprintf(stderr, "no .riv file specified");
    abort();
  }

  player.init();

#ifdef __EMSCRIPTEN__
  emscripten_set_main_loop(
      []() {
        if (!player.doFrame())
        {
          player_shutdown();
        }
      },
      0,
      true);
#else
  for (;;)
  {
    rive::gpu::ScopedAutoreleasePool autoreleasePool;
    if (!player.doFrame())
    {
      player_shutdown();
    }
  }
#endif

  return 0;
}

#endif // !RIVE_UNREAL

#endif
