// Copyright 2017 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 "garnet/examples/escher/common/demo_harness_fuchsia.h"

#include <hid/usages.h>
#include <lib/async/cpp/task.h>
#include <lib/async/default.h>
#include <zx/time.h>

#include "garnet/examples/escher/common/demo.h"
#include "lib/escher/util/trace_macros.h"

namespace {

class DemoKeyDispatcher : public fuchsia::ui::input::InputDevice {
 public:
  DemoKeyDispatcher(Demo* demo) : demo_(demo) {}

 private:
  // |fuchsia::ui::input::InputDevice|
  void DispatchReport(fuchsia::ui::input::InputReport report) override {
    if (report.keyboard) {
      DispatchDelta(std::move(report.keyboard->pressed_keys));
    }
  }

  // Dispatch only keys that are newly pressed.
  void DispatchDelta(std::vector<uint32_t> pressed_keys) {
    for (uint32_t key : pressed_keys) {
      // Since this is a demo harness, we can assume a small number of pressed
      // keys. However, if this assumption breaks, we can switch to std::bitset.
      if (std::find(pressed_keys_.begin(), pressed_keys_.end(), key) ==
          pressed_keys_.end()) {
        DispatchKey(key);
      }
    }
    pressed_keys_ = std::move(pressed_keys);
  }

  void DispatchKey(uint32_t hid) {
    if (hid >= HID_USAGE_KEY_A && hid <= HID_USAGE_KEY_Z) {
      demo_->HandleKeyPress(std::string(1, 'A' + hid - HID_USAGE_KEY_A));
    } else if (hid >= HID_USAGE_KEY_1 && hid <= HID_USAGE_KEY_9) {
      demo_->HandleKeyPress(std::string(1, '1' + hid - HID_USAGE_KEY_1));
    } else {
      switch (hid) {
        // Unlike ASCII, HID_USAGE_KEY_0 comes after 9.
        case HID_USAGE_KEY_0:
          demo_->HandleKeyPress("0");
          break;
        case HID_USAGE_KEY_ENTER:
        case HID_USAGE_KEY_KP_ENTER:
          demo_->HandleKeyPress("RETURN");
          break;
        case HID_USAGE_KEY_ESC:
          demo_->HandleKeyPress("ESCAPE");
          break;
        case HID_USAGE_KEY_SPACE:
          demo_->HandleKeyPress("SPACE");
          break;
        default:
          break;
      }
    }
  }

  Demo* demo_;
  std::vector<uint32_t> pressed_keys_;
};

}  // namespace

// When running on Fuchsia, New() instantiates a DemoHarnessFuchsia.
std::unique_ptr<DemoHarness> DemoHarness::New(
    DemoHarness::WindowParams window_params,
    DemoHarness::InstanceParams instance_params) {
  auto harness = new DemoHarnessFuchsia(nullptr, window_params);
  harness->Init(std::move(instance_params));
  return std::unique_ptr<DemoHarness>(harness);
}

DemoHarnessFuchsia::DemoHarnessFuchsia(async::Loop* loop,
                                       WindowParams window_params)
    : DemoHarness(window_params),
      loop_(loop),
      owned_loop_(loop_ ? nullptr
                        : new async::Loop(&kAsyncLoopConfigAttachToThread)),
      trace_provider_((loop_ ? loop_ : owned_loop_.get())->dispatcher()),
      startup_context_(component::StartupContext::CreateFromStartupInfo()),
      input_reader_(this) {
  // Provide a PseudoDir where the demo can register debugging services.
  fbl::RefPtr<fs::PseudoDir> debug_dir(fbl::AdoptRef(new fs::PseudoDir));
  startup_context()->outgoing().debug_dir()->AddEntry("demo", debug_dir);
  filesystem_ = escher::HackFilesystem::New(debug_dir);

  if (!loop_) {
    loop_ = owned_loop_.get();
  }
}

void DemoHarnessFuchsia::InitWindowSystem() { input_reader_.Start(); }

vk::SurfaceKHR DemoHarnessFuchsia::CreateWindowAndSurface(
    const WindowParams& params) {
  VkMagmaSurfaceCreateInfoKHR create_info = {
      .sType = VK_STRUCTURE_TYPE_MAGMA_SURFACE_CREATE_INFO_KHR,
      .pNext = nullptr,
  };
  VkSurfaceKHR surface;
  VkResult err =
      vkCreateMagmaSurfaceKHR(instance(), &create_info, nullptr, &surface);
  FXL_CHECK(!err);
  return surface;
}

void DemoHarnessFuchsia::AppendPlatformSpecificInstanceExtensionNames(
    InstanceParams* params) {
  params->extension_names.insert(VK_KHR_SURFACE_EXTENSION_NAME);
  params->extension_names.insert(VK_KHR_MAGMA_SURFACE_EXTENSION_NAME);
}

void DemoHarnessFuchsia::ShutdownWindowSystem() {}

void DemoHarnessFuchsia::Run(Demo* demo) {
  FXL_CHECK(!demo_);
  demo_ = demo;
  async::PostTask(loop_->dispatcher(), [this] { this->RenderFrameOrQuit(); });
  loop_->Run();
}

void DemoHarnessFuchsia::RegisterDevice(
    fuchsia::ui::input::DeviceDescriptor descriptor,
    fidl::InterfaceRequest<fuchsia::ui::input::InputDevice> input_device) {
  if (descriptor.keyboard) {
    input_devices_.AddBinding(std::make_unique<DemoKeyDispatcher>(demo_),
                              std::move(input_device));
  }
}

void DemoHarnessFuchsia::RenderFrameOrQuit() {
  FXL_CHECK(demo_);  // Must be running.
  if (ShouldQuit()) {
    loop_->Quit();
    device().waitIdle();
  } else {
    demo_->MaybeDrawFrame();
    async::PostDelayedTask(loop_->dispatcher(),
                           [this] { this->RenderFrameOrQuit(); }, zx::msec(1));
  }
}
