// 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 "src/ui/scenic/bin/app.h"

#include <lib/fit/bridge.h>
#include <lib/fit/function.h>
#include <lib/fit/single_threaded_executor.h>
#include <lib/syslog/cpp/logger.h>

#ifdef SCENIC_ENABLE_GFX_SUBSYSTEM
#include "src/ui/scenic/lib/gfx/gfx_system.h"
#endif

#ifdef SCENIC_ENABLE_INPUT_SUBSYSTEM
#include "src/ui/scenic/lib/input/input_system.h"
#endif

#include "src/lib/cobalt/cpp/cobalt_logger.h"
#include "src/lib/files/file.h"
#include "src/ui/lib/escher/vk/pipeline_builder.h"
#include "src/ui/scenic/lib/gfx/api/internal_snapshot_impl.h"
#include "src/ui/scenic/lib/scheduling/default_frame_scheduler.h"
#include "src/ui/scenic/lib/scheduling/frame_metrics_registry.cb.h"
#include "src/ui/scenic/lib/scheduling/windowed_frame_predictor.h"

namespace {

// Wait for /dev/class/display-controller on x86 as that's sufficient for Intel GPU driver and
// supports AEMU and swiftshader, which don't depend on devices in /dev/class/gpu.
//
// TODO(SCN-568): Scenic should not be aware of these type of dependencies.
#if defined(__x86_64__)
static const std::string kDependencyDir = "/dev/class/display-controller";
#else
static const std::string kDependencyDir = "/dev/class/gpu";
#endif

// A limited System used only to limit Scenic from fully initializing, without introducing a new
// command dispatcher.
//
// TODO(SCN-1506): Find a better way to represent this other than creating an entire dummy system.
class Dependency : public scenic_impl::System {
 public:
  using System::System;
  scenic_impl::CommandDispatcherUniquePtr CreateCommandDispatcher(
      scheduling::SessionId session_id, std::shared_ptr<scenic_impl::EventReporter> event_reporter,
      std::shared_ptr<scenic_impl::ErrorReporter> error_reporter) override {
    return nullptr;
  };
};

zx::duration GetMinimumPredictedFrameDuration() {
  std::string frame_scheduler_min_predicted_frame_duration;
  int frame_scheduler_min_predicted_frame_duration_in_us = 0;
  if (files::ReadFileToString("/config/data/frame_scheduler_min_predicted_frame_duration_in_us",
                              &frame_scheduler_min_predicted_frame_duration)) {
    frame_scheduler_min_predicted_frame_duration_in_us =
        atoi(frame_scheduler_min_predicted_frame_duration.c_str());
    FX_DCHECK(frame_scheduler_min_predicted_frame_duration_in_us >= 0);
    FX_LOGS(INFO) << "min_predicted_frame_duration(us): "
                  << frame_scheduler_min_predicted_frame_duration_in_us;
  }
  return frame_scheduler_min_predicted_frame_duration_in_us > 0
             ? zx::usec(frame_scheduler_min_predicted_frame_duration_in_us)
             : scheduling::DefaultFrameScheduler::kMinPredictedFrameDuration;
}

}  // namespace

namespace scenic_impl {

DisplayInfoDelegate::DisplayInfoDelegate(std::shared_ptr<display::Display> display_)
    : display_(display_) {
  FX_CHECK(display_);
}

void DisplayInfoDelegate::GetDisplayInfo(
    fuchsia::ui::scenic::Scenic::GetDisplayInfoCallback callback) {
  auto info = ::fuchsia::ui::gfx::DisplayInfo();
  info.width_in_px = display_->width_in_px();
  info.height_in_px = display_->height_in_px();

  callback(std::move(info));
}

void DisplayInfoDelegate::GetDisplayOwnershipEvent(
    fuchsia::ui::scenic::Scenic::GetDisplayOwnershipEventCallback callback) {
  // These constants are defined as raw hex in the FIDL file, so we confirm here that they are the
  // same values as the expected constants in the ZX headers.
  static_assert(fuchsia::ui::scenic::displayNotOwnedSignal == ZX_USER_SIGNAL_0, "Bad constant");
  static_assert(fuchsia::ui::scenic::displayOwnedSignal == ZX_USER_SIGNAL_1, "Bad constant");

  zx::event dup;
  if (display_->ownership_event().duplicate(ZX_RIGHTS_BASIC, &dup) != ZX_OK) {
    FX_LOGS(ERROR) << "Display ownership event duplication error.";
    callback(zx::event());
  } else {
    callback(std::move(dup));
  }
}

App::App(std::unique_ptr<sys::ComponentContext> app_context, inspect::Node inspect_node,
         fit::closure quit_callback)
    : executor_(async_get_default_dispatcher()),
      app_context_(std::move(app_context)),
      // TODO(40997): subsystems requiring graceful shutdown *on a loop* should register themselves.
      // It is preferable to cleanly shutdown using destructors only, if possible.
      shutdown_manager_(
          ShutdownManager::New(async_get_default_dispatcher(), std::move(quit_callback))),
      scenic_(app_context_.get(), std::move(inspect_node),
              [weak = std::weak_ptr<ShutdownManager>(shutdown_manager_)] {
                if (auto strong = weak.lock()) {
                  strong->Shutdown(LifecycleControllerImpl::kShutdownTimeout);
                }
              }),
      annotation_registry_(app_context_.get()),
      lifecycle_controller_impl_(app_context_.get(),
                                 std::weak_ptr<ShutdownManager>(shutdown_manager_)) {
  FX_DCHECK(!device_watcher_);

  fit::bridge<escher::EscherUniquePtr> escher_bridge;
  fit::bridge<std::shared_ptr<scenic_impl::display::Display>> display_bridge;

  device_watcher_ = fsl::DeviceWatcher::Create(
      kDependencyDir, [this, completer = std::move(escher_bridge.completer)](
                          int dir_fd, std::string filename) mutable {
        completer.complete_ok(gfx::GfxSystem::CreateEscher(app_context_.get()));
        device_watcher_.reset();
      });

  display_manager_.WaitForDefaultDisplayController(
      [this, completer = std::move(display_bridge.completer)]() mutable {
        completer.complete_ok(display_manager_.default_display_shared());
      });

  auto p =
      fit::join_promises(escher_bridge.consumer.promise(), display_bridge.consumer.promise())
          .and_then([this](std::tuple<fit::result<escher::EscherUniquePtr>,
                                      fit::result<std::shared_ptr<scenic_impl::display::Display>>>&
                               results) {
            InitializeServices(std::move(std::get<0>(results).value()),
                               std::move(std::get<1>(results).value()));
          });

  executor_.schedule_task(std::move(p));

  // TODO(48596): Scenic sometimes gets stuck for consecutive 60 seconds.
  // Here we set up a Watchdog polling Scenic status every 15 seconds.
  constexpr uint32_t kWatchdogWarningIntervalMs = 15000u;

  // On some devices, the time to start up Scenic may exceed 15 seconds.
  // In that case we should only send a warning, and we should only crash
  // Scenic if the main thread is blocked for longer time.
  constexpr uint32_t kWatchdogTimeoutMs = 45000u;

  watchdog_ = std::make_unique<Watchdog>(kWatchdogWarningIntervalMs, kWatchdogTimeoutMs,
                                         async_get_default_dispatcher());
}

void App::InitializeServices(escher::EscherUniquePtr escher,
                             std::shared_ptr<display::Display> display) {
  TRACE_DURATION("gfx", "App::InitializeServices");

  if (!display) {
    FX_LOGS(ERROR) << "No default display, Graphics system exiting";
    shutdown_manager_->Shutdown(LifecycleControllerImpl::kShutdownTimeout);
    return;
  }

  if (!escher || !escher->device()) {
    FX_LOGS(ERROR) << "No Vulkan on device, Graphics system exiting.";
    shutdown_manager_->Shutdown(LifecycleControllerImpl::kShutdownTimeout);
    return;
  }

  escher_ = std::move(escher);

  std::shared_ptr<cobalt::CobaltLogger> cobalt_logger = cobalt::NewCobaltLoggerFromProjectId(
      async_get_default_dispatcher(), app_context_->svc(), cobalt_registry::kProjectId);
  if (!cobalt_logger) {
    FX_LOGS(ERROR) << "CobaltLogger creation failed!";
  }

  // Replace Escher's default pipeline builder with one which will log to Cobalt upon each
  // unexpected lazy pipeline creation.  This allows us to detect when this slips through our
  // testing and occurs in the wild.  In order to detect problems ASAP during development, debug
  // builds CHECK instead of logging to Cobalt.
  {
    auto pipeline_builder = std::make_unique<escher::PipelineBuilder>(escher_->vk_device());
    pipeline_builder->set_log_pipeline_creation_callback(
        [cobalt_logger](const vk::GraphicsPipelineCreateInfo* graphics_info,
                        const vk::ComputePipelineCreateInfo* compute_info) {
          // TODO(49972): pre-warm compute pipelines in addition to graphics pipelines.
          if (compute_info) {
            FX_LOGS(WARNING) << "Unexpected lazy creation of Vulkan compute pipeline.";
            return;
          }

#if !defined(NDEBUG)
          FX_CHECK(false)  // debug builds should crash for early detection
#else
          FX_LOGS(WARNING)  // release builds should log to Cobalt, see below.
#endif
              << "Unexpected lazy creation of Vulkan pipeline.";

          cobalt_logger->LogEvent(
              cobalt_registry::kScenicRareEventMetricId,
              cobalt_registry::ScenicRareEventMetricDimensionEvent_LazyPipelineCreation);
        });
    escher_->set_pipeline_builder(std::move(pipeline_builder));
  }

  {
    TRACE_DURATION("gfx", "App::InitializeServices[frame-scheduler]");
    frame_scheduler_ = std::make_shared<scheduling::DefaultFrameScheduler>(
        display->vsync_timing(),
        std::make_unique<scheduling::WindowedFramePredictor>(
            GetMinimumPredictedFrameDuration(),
            scheduling::DefaultFrameScheduler::kInitialRenderDuration,
            scheduling::DefaultFrameScheduler::kInitialUpdateDuration),
        scenic_.inspect_node()->CreateChild("FrameScheduler"), cobalt_logger);
  }

  {
    TRACE_DURATION("gfx", "App::InitializeServices[engine]");
    engine_.emplace(app_context_.get(), frame_scheduler_, escher_->GetWeakPtr(),
                    scenic_.inspect_node()->CreateChild("Engine"));
  }
  frame_scheduler_->SetFrameRenderer(engine_->GetWeakPtr());
  scenic_.SetFrameScheduler(frame_scheduler_);
  annotation_registry_.InitializeWithGfxAnnotationManager(engine_->annotation_manager());

#ifdef SCENIC_ENABLE_GFX_SUBSYSTEM
  auto gfx = scenic_.RegisterSystem<gfx::GfxSystem>(&engine_.value(), &sysmem_, &display_manager_);
  FX_DCHECK(gfx);

  frame_scheduler_->AddSessionUpdater(gfx->GetWeakPtr());
  scenic_.SetScreenshotDelegate(gfx);
  display_info_delegate_ = std::make_unique<DisplayInfoDelegate>(display);
  scenic_.SetDisplayInfoDelegate(display_info_delegate_.get());
#endif

#ifdef SCENIC_ENABLE_INPUT_SUBSYSTEM
  auto input = scenic_.RegisterSystem<input::InputSystem>(engine_.value().scene_graph());
  FX_DCHECK(input);
#endif

  // Create the snapshotter and pass it to scenic.
  auto snapshotter =
      std::make_unique<gfx::InternalSnapshotImpl>(engine_->scene_graph(), escher_->GetWeakPtr());
  scenic_.InitializeSnapshotService(std::move(snapshotter));

  scenic_.SetInitialized(engine_->scene_graph());
}

}  // namespace scenic_impl
