// 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 "flutter/shell/common/shell.h"

#include "flutter/benchmarking/benchmarking.h"
#include "flutter/fml/logging.h"
#include "flutter/runtime/dart_vm.h"
#include "flutter/shell/common/thread_host.h"
#include "flutter/testing/elf_loader.h"
#include "flutter/testing/testing.h"

namespace flutter {

static void StartupAndShutdownShell(benchmark::State& state,
                                    bool measure_startup,
                                    bool measure_shutdown) {
  auto assets_dir = fml::OpenDirectory(testing::GetFixturesPath(), false,
                                       fml::FilePermission::kRead);
  std::unique_ptr<Shell> shell;
  std::unique_ptr<ThreadHost> thread_host;
  testing::ELFAOTSymbols aot_symbols;

  {
    benchmarking::ScopedPauseTiming pause(state, !measure_startup);
    Settings settings = {};
    settings.task_observer_add = [](intptr_t, const fml::closure&) {};
    settings.task_observer_remove = [](intptr_t) {};

    if (DartVM::IsRunningPrecompiledCode()) {
      aot_symbols = testing::LoadELFSymbolFromFixturesIfNeccessary(
          testing::kDefaultAOTAppELFFileName);
      FML_CHECK(
          testing::PrepareSettingsForAOTWithSymbols(settings, aot_symbols))
          << "Could not set up settings with AOT symbols.";
    } else {
      settings.application_kernels = [&]() {
        std::vector<std::unique_ptr<const fml::Mapping>> kernel_mappings;
        kernel_mappings.emplace_back(
            fml::FileMapping::CreateReadOnly(assets_dir, "kernel_blob.bin"));
        return kernel_mappings;
      };
    }

    thread_host = std::make_unique<ThreadHost>(ThreadHost::ThreadHostConfig(
        "io.flutter.bench.", ThreadHost::Type::Platform |
                                 ThreadHost::Type::RASTER |
                                 ThreadHost::Type::IO | ThreadHost::Type::UI));

    TaskRunners task_runners("test",
                             thread_host->platform_thread->GetTaskRunner(),
                             thread_host->raster_thread->GetTaskRunner(),
                             thread_host->ui_thread->GetTaskRunner(),
                             thread_host->io_thread->GetTaskRunner());

    shell = Shell::Create(
        flutter::PlatformData(), task_runners, settings,
        [](Shell& shell) {
          return std::make_unique<PlatformView>(shell, shell.GetTaskRunners());
        },
        [](Shell& shell) { return std::make_unique<Rasterizer>(shell); });
  }

  FML_CHECK(shell);

  {
    // The ui thread could be busy processing tasks after shell created, e.g.,
    // default font manager setup. The measurement of shell shutdown should be
    // considered after those ui tasks have been done.
    //
    // However, if we're measuring the complete time from startup to shutdown,
    // this time should still be included.
    benchmarking::ScopedPauseTiming pause(
        state, !measure_shutdown || !measure_startup);
    fml::AutoResetWaitableEvent latch;
    fml::TaskRunner::RunNowOrPostTask(thread_host->ui_thread->GetTaskRunner(),
                                      [&latch]() { latch.Signal(); });
    latch.Wait();
  }

  {
    benchmarking::ScopedPauseTiming pause(state, !measure_shutdown);
    // Shutdown must occur synchronously on the platform thread.
    fml::AutoResetWaitableEvent latch;
    fml::TaskRunner::RunNowOrPostTask(
        thread_host->platform_thread->GetTaskRunner(),
        [&shell, &latch]() mutable {
          shell.reset();
          latch.Signal();
        });
    latch.Wait();
    thread_host.reset();
  }

  FML_CHECK(!shell);
}

static void BM_ShellInitialization(benchmark::State& state) {
  while (state.KeepRunning()) {
    StartupAndShutdownShell(state, true, false);
  }
}

BENCHMARK(BM_ShellInitialization);

static void BM_ShellShutdown(benchmark::State& state) {
  while (state.KeepRunning()) {
    StartupAndShutdownShell(state, false, true);
  }
}

BENCHMARK(BM_ShellShutdown);

static void BM_ShellInitializationAndShutdown(benchmark::State& state) {
  while (state.KeepRunning()) {
    StartupAndShutdownShell(state, true, true);
  }
}

BENCHMARK(BM_ShellInitializationAndShutdown);

}  // namespace flutter
