// 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 "garnet/examples/ui/lab/direct_input/app.h"

#include <fuchsia/math/cpp/fidl.h>
#include <lib/fdio/fd.h>
#include <lib/fit/function.h>
#include <lib/sys/cpp/file_descriptor.h>
#include <lib/ui/input/cpp/formatting.h>
#include <lib/ui/scenic/cpp/resources.h>
#include <lib/ui/scenic/cpp/view_token_pair.h>
#include <lib/zx/time.h>
#include <zircon/processargs.h>

#include <limits>
#include <string>
#include <utility>

namespace direct_input {

const uint32_t kNoFinger = std::numeric_limits<uint32_t>::max();  // Sentinel.

App::App(async::Loop* loop)
    : startup_context_(component::StartupContext::CreateFromStartupInfo()),
      message_loop_(loop),
      input_reader_(this),
      next_device_token_(0),
      focused_(false) {
  FXL_DCHECK(startup_context_);

  scenic_ = startup_context_
                ->ConnectToEnvironmentService<fuchsia::ui::scenic::Scenic>();
  scenic_.set_error_handler([this](zx_status_t status) { OnScenicError(); });
  FXL_LOG(INFO) << "DirectInput - scenic connection";

  session_ = std::make_unique<scenic::Session>(scenic_.get());
  session_->SetDebugName("Direct Input");
  session_->set_error_handler(
      [this](zx_status_t status) { this->OnSessionError(); });
  session_->set_event_handler(fit::bind_member(this, &App::OnSessionEvents));
  FXL_LOG(INFO) << "DirectInput - session set up";

  compositor_ = std::make_unique<scenic::DisplayCompositor>(session_.get());
  FXL_LOG(INFO) << "DirectInput - compositor set up";

  input_reader_.Start();
  startup_context_->outgoing().AddPublicService(
      input_device_registry_bindings_.GetHandler(this));
  FXL_LOG(INFO) << "DirectInput - input set up (Press ESC to quit).";

  scenic_->GetDisplayInfo([this](fuchsia::ui::gfx::DisplayInfo display_info) {
    CreateScene(display_info.width_in_px, display_info.height_in_px);
    UpdateScene(zx_clock_get_monotonic());
  });

  {
    component::Services child_services;
    fuchsia::sys::LaunchInfo launch_info;
    launch_info.out = sys::CloneFileDescriptor(STDOUT_FILENO);
    launch_info.err = sys::CloneFileDescriptor(STDERR_FILENO);
    launch_info.url =
        "fuchsia-pkg://fuchsia.com/direct_input_child#meta/"
        "direct_input_child.cmx";
    launch_info.directory_request = child_services.NewRequest();
    startup_context_->launcher()->CreateComponent(
        std::move(launch_info), child_controller_.NewRequest());
    child_services.ConnectToService(child_view_provider_.NewRequest(),
                                    "view_provider");
  }

  {
    fuchsia::ui::input::SetHardKeyboardDeliveryCmd cmd;
    cmd.delivery_request = true;
    fuchsia::ui::input::Command input_cmd;
    input_cmd.set_set_hard_keyboard_delivery(std::move(cmd));
    session_->Enqueue(std::move(input_cmd));
  }

  FXL_LOG(INFO) << "DirectInput - child set up";
}

App::~App() { ReleaseSessionResources(); }

void App::ReleaseSessionResources() {
  if (session_) {
    compositor_.reset();
    camera_.reset();
    focus_frame_.reset();
    for (size_t i = 0; i < 10; ++i) {
      pointer_id_[i] = kNoFinger;
      pointer_tracker_[i].reset();
    }
    view_.reset();
    view_holder_.reset();
    child_view_holder_.reset();

    session_->Flush();
    session_.reset();
  }
}

void App::CheckQuit(const fuchsia::ui::input::InputEvent& event) {
  if (event.is_keyboard()) {
    fuchsia::ui::input::KeyboardEvent key_event = event.keyboard();
    if (key_event.hid_usage == /* Esc key */ 0x29 &&
        key_event.phase == fuchsia::ui::input::KeyboardEventPhase::RELEASED) {
      FXL_LOG(INFO) << "DirectInput - shutting down.";
      child_controller_->Kill();
      async::PostTask(message_loop_->dispatcher(),
                      [this]() { OnSessionClose(); });
    }
  }
}

void App::OnScenicError() {
  FXL_LOG(ERROR) << "DirectInput - scenic connection error.";
  ReleaseSessionResources();
  message_loop_->Quit();
}

void App::OnSessionError() {
  FXL_LOG(ERROR) << "DirectInput - session error.";
  ReleaseSessionResources();
  message_loop_->Quit();
}

void App::OnSessionClose() {
  FXL_LOG(INFO) << "DirectInput - session close.";
  ReleaseSessionResources();
  message_loop_->Quit();
}

void App::OnSessionEvents(std::vector<fuchsia::ui::scenic::Event> events) {
  using InputEvent = fuchsia::ui::input::InputEvent;
  using InputType = fuchsia::ui::input::InputEvent::Tag;

  for (const auto& event : events) {
    if (event.is_input()) {
      const InputEvent& input_event = event.input();
      switch (input_event.Which()) {
        case InputType::kPointer:
          OnPointerEvent(input_event.pointer());
          continue;
        case InputType::kKeyboard:
          OnKeyboardEvent(input_event.keyboard());
          continue;
        case InputType::kFocus:
          OnFocusEvent(input_event.focus());
          continue;
        case InputType::Invalid:
          FXL_LOG(FATAL) << "Unknown input event received.";
      }
    } else if (event.is_gfx()) {
      FXL_LOG(ERROR) << "DirectInput - GFX command unimplemented.";
    }
  }
}

void App::OnFocusEvent(const fuchsia::ui::input::FocusEvent& event) {
  focused_ = event.focused;
  if (focused_) {
    view_->AddChild(*focus_frame_);
  } else {
    view_->DetachChild(*focus_frame_);
  }
}

void App::OnKeyboardEvent(const fuchsia::ui::input::KeyboardEvent& event) {
  using Phase = fuchsia::ui::input::KeyboardEventPhase;
  // "Blink" the focus frame to acknowledge keyboard event.
  if (event.phase == Phase::PRESSED) {
    view_->DetachChild(*focus_frame_);
    async::PostDelayedTask(
        message_loop_->dispatcher(),
        [this]() {
          if (focused_) {
            view_->AddChild(*focus_frame_);
          }
        },
        zx::msec(80));
  }
}

// Helper function for OnPointerEvent.  Find index of matching element.
template <std::size_t N>
static size_t find_idx(const std::array<uint32_t, N>& array, uint32_t elem) {
  for (size_t i = 0; i < N; ++i) {
    if (array[i] == elem) {
      return i;
    }
  }
  return kNoFinger;  // Keep it simple.
}

// Helper function for OnPointerEvent.  Return contents of array as a string.
template <std::size_t N>
static std::string contents(const std::array<uint32_t, N>& array) {
  std::string value = "[";
  for (size_t i = 0; i < N; ++i) {
    value += std::to_string(array[i]);
    if (i < N - 1) {
      value += ", ";
    }
  }
  return value + "]";
}

// This function implements a very specific input-recognition behavior.
// Despite parallel dispatch of input events on a DOWN hit, we only track a
// pointer if we are also focused. In contrast, gestures need to see all inputs,
// regardless of focus state.
void App::OnPointerEvent(const fuchsia::ui::input::PointerEvent& event) {
  using Type = fuchsia::ui::input::PointerEventType;
  using Phase = fuchsia::ui::input::PointerEventPhase;

  if (event.type == Type::TOUCH) {
    // TODO(SCN-920): Reduce the very noticeable tracking lag.
    if (focused_ && event.phase == Phase::DOWN) {
      // Nice to meet you. Add to known-fingers list.
      size_t idx = find_idx(pointer_id_, kNoFinger);
      FXL_CHECK(idx != kNoFinger)
          << "Pointer index full: " << contents(pointer_id_);
      pointer_id_[idx] = event.pointer_id;
      view_->AddChild(*pointer_tracker_[idx]);
      pointer_tracker_[idx]->SetTranslation(event.x, event.y, -400.f);

    } else if (event.phase == Phase::MOVE) {
      size_t idx = find_idx(pointer_id_, event.pointer_id);
      if (idx != kNoFinger) {
        // It's a finger we know, keep moving.
        pointer_tracker_[idx]->SetTranslation(event.x, event.y, -400.f);
      }

    } else if (event.phase == Phase::UP || event.phase == Phase::CANCEL) {
      size_t idx = find_idx(pointer_id_, event.pointer_id);
      if (idx != kNoFinger) {
        // It's a finger we know, but time to remove.
        view_->DetachChild(*pointer_tracker_[idx]);
        pointer_id_[idx] = kNoFinger;
      }
    }
  }
}

void App::UpdateScene(uint64_t next_presentation_time) {
  session_->Present(
      next_presentation_time, [this](fuchsia::images::PresentationInfo info) {
        UpdateScene(info.presentation_time + 2 * info.presentation_interval);
      });
}

void App::CreateScene(float display_width, float display_height) {
  FXL_LOG(INFO) << "DirectInput - display size: " << display_width << ", "
                << display_height;

  const float kMargin = 100.f;
  const float kRootWidth = display_width - 2.f * kMargin;
  const float kRootHeight = display_height - 2.f * kMargin;

  width_in_px_ = display_width;  // Store display size, not view size!
  height_in_px_ = display_height;

  auto session = session_.get();

  scenic::LayerStack layer_stack(session);
  compositor_->SetLayerStack(layer_stack);

  // Set up scene.
  scenic::Scene scene(session);
  {
    camera_ = std::make_unique<scenic::Camera>(scene);
    scenic::Renderer renderer(session);
    renderer.SetCamera(camera_->id());

    scenic::Layer layer(session);
    layer.SetRenderer(renderer);
    layer.SetSize(display_width, display_height);  // Need screen size, SCN-248.
    layer_stack.AddLayer(layer);

    scenic::AmbientLight ambient_light(session);
    ambient_light.SetColor(0.3f, 0.3f, 0.3f);
    scene.AddLight(ambient_light);

    scenic::DirectionalLight directional_light(session);
    directional_light.SetColor(0.7f, 0.7f, 0.7f);
    directional_light.SetDirection(1.f, 1.f, -2.f);
    scene.AddLight(directional_light);

    FXL_LOG(INFO) << "DirectInput - scene is set up.";
  }

  // Set up root node, its dimensions, add green background.
  scenic::EntityNode root_node(session);
  {
    const float kElevation = 10.f;

    root_node.SetLabel("root_node");
    root_node.SetClip(0, true);
    root_node.SetTranslation(display_width * 0.5f, display_height * 0.5f,
                             -kElevation);

    scenic::ShapeNode background(session);
    scenic::Rectangle shape(session, kRootWidth, kRootHeight);
    background.SetShape(shape);
    scenic::Material material(session);
    material.SetColor(0, 255, 0, 255);  // Green
    background.SetMaterial(material);
    root_node.AddPart(background);

    scene.AddChild(root_node);
    FXL_LOG(INFO) << "DirectInput - root node is set up.";
  }

  // Create View/ViewHolder. Attach ViewHolder to root node.
  {
    auto [view_token, view_holder_token] = scenic::ViewTokenPair::New();

    view_holder_ = std::make_unique<scenic::ViewHolder>(
        session, std::move(view_holder_token), "view_holder");
    view_holder_->SetLabel("main view_holder");
    view_ =
        std::make_unique<scenic::View>(session, std::move(view_token), "view");
    view_->SetLabel("main view");

    root_node.Attach(*view_holder_);
    FXL_LOG(INFO) << "DirectInput - View/ViewHolder pair created.";
  }

  const float kMainWidth = display_width - 4.f * kMargin;
  const float kMainHeight = display_height - 4.f * kMargin;

  // Create main node, attach to View. Main node is accessible only from View.
  {
    const float kElevation = 20.f;

    scenic::ShapeNode node(session);
    node.SetLabel("main node");
    scenic::Rectangle shape(session, kMainWidth, kMainHeight);
    node.SetShape(shape);
    scenic::Material material(session);
    material.SetColor(255, 0, 255, 255);  // Fuchsia
    node.SetMaterial(material);
    node.SetTranslation(0.f, 0.f, -kElevation);
    view_->AddChild(node);
    FXL_LOG(INFO) << "DirectInput - main node added to view.";
  }

  // Create frame to trigger on focus to main node.
  {
    std::unique_ptr<scenic::EntityNode> frame =
        std::make_unique<scenic::EntityNode>(session);
    frame->SetLabel("focus frame");

    const float kElevation = 30.f;  // Z height
    const float kBar = 50.f;        // bar thickness
    const float kTranslateX = (kMainWidth - kBar) * 0.5f;
    const float kTranslateY = (kMainHeight - kBar) * 0.5f;

    scenic::Material material(session);
    material.SetColor(128, 0, 128, 255);  // Purple
    scenic::Rectangle horizontal_bar(session, kMainWidth, kBar);
    scenic::Rectangle vertical_bar(session, kBar, kMainHeight);

    scenic::ShapeNode top_bar(session);
    top_bar.SetTranslation(0.f, -kTranslateY, -kElevation);
    top_bar.SetShape(horizontal_bar);
    top_bar.SetMaterial(material);
    frame->AddPart(top_bar);

    scenic::ShapeNode bottom_bar(session);
    bottom_bar.SetTranslation(0.f, kTranslateY, -kElevation);
    bottom_bar.SetShape(horizontal_bar);
    bottom_bar.SetMaterial(material);
    frame->AddPart(bottom_bar);

    scenic::ShapeNode left_bar(session);
    left_bar.SetTranslation(-kTranslateX, 0, -kElevation);
    left_bar.SetShape(vertical_bar);
    left_bar.SetMaterial(material);
    frame->AddPart(left_bar);

    scenic::ShapeNode right_bar(session);
    right_bar.SetTranslation(kTranslateX, 0, -kElevation);
    right_bar.SetShape(vertical_bar);
    right_bar.SetMaterial(material);
    frame->AddPart(right_bar);

    focus_frame_ = std::move(frame);
    FXL_LOG(INFO) << "DirectInput - focus frame prepared.";
  }

  // Create a visual tracker for pointer movement.
  {
    const float kElevation = 400.f;

    for (size_t i = 0; i < 10; ++i) {
      pointer_id_[i] = kNoFinger;

      pointer_tracker_[i] = std::make_unique<scenic::ShapeNode>(session);
      pointer_tracker_[i]->SetLabel("pointer tracker");
      pointer_tracker_[i]->SetTranslation(0.f, 0.f, -kElevation);

      scenic::Circle circle(session, 50.f);
      pointer_tracker_[i]->SetShape(circle);

      scenic::Material material(session);
      material.SetColor(128, 0, 128, 255);  // Purple
      pointer_tracker_[i]->SetMaterial(material);
    }

    FXL_LOG(INFO) << "DirectInput - pointer tracker prepared.";
  }

  // Connect to child view, put it in a ViewHolder.
  {
    zx::eventpair view_holder;
    zx::eventpair view;
    zx_status_t status = zx::eventpair::create(0u, &view_holder, &view);
    FXL_CHECK(status == ZX_OK);
    child_view_provider_->CreateView(std::move(view), nullptr, nullptr);

    child_view_holder_ = std::make_unique<scenic::ViewHolder>(
        session, std::move(view_holder), "child view holder");
    child_view_holder_->SetLabel("child_view_holder");

    root_node.Attach(*child_view_holder_);
    FXL_LOG(INFO) << "DirectInput - child view requested, view holder set up.";
  }
}

void App::OnDeviceSensorEvent(uint32_t device_id,
                              fuchsia::ui::input::InputReport event) {
  FXL_VLOG(3) << "DirectInput - OnDeviceSensorEvent(device_id=" << device_id
              << "): " << event;
}

void App::OnDeviceInputEvent(uint32_t compositor_id,
                             fuchsia::ui::input::InputEvent event) {
  FXL_VLOG(1) << "DirectInput - OnDeviceInputEvent: " << event;

  CheckQuit(event);

  fuchsia::ui::input::Command command;
  if (event.is_pointer()) {
    // Pointer events are tied to a particular compositor for routing.
    fuchsia::ui::input::SendPointerInputCmd cmd;
    cmd.pointer_event = std::move(event.pointer());
    cmd.compositor_id = compositor_id;
    command.set_send_pointer_input(std::move(cmd));
  } else if (event.is_keyboard()) {
    // Keyboard events are sent to a focused view, wherever that may be.
    fuchsia::ui::input::SendKeyboardInputCmd cmd;
    cmd.keyboard_event = std::move(event.keyboard());
    cmd.compositor_id = compositor_id;
    command.set_send_keyboard_input(std::move(cmd));
  }
  session_->Enqueue(std::move(command));
}

void App::RegisterDevice(fuchsia::ui::input::DeviceDescriptor descriptor,
                         fidl::InterfaceRequest<fuchsia::ui::input::InputDevice>
                             input_device_request) {
  uint32_t device_id = ++next_device_token_;

  FXL_VLOG(2) << "DirectInput - RegisterDevice: " << device_id << " "
              << descriptor;
  std::unique_ptr<ui_input::InputDeviceImpl> input_device =
      std::make_unique<ui_input::InputDeviceImpl>(
          device_id, std::move(descriptor), std::move(input_device_request),
          this);

  std::unique_ptr<ui_input::DeviceState> state;
  if (input_device->descriptor()->sensor) {
    ui_input::OnSensorEventCallback callback =
        [this](uint32_t device_id, fuchsia::ui::input::InputReport event) {
          OnDeviceSensorEvent(device_id, std::move(event));
        };
    state = std::make_unique<ui_input::DeviceState>(
        input_device->id(), input_device->descriptor(), std::move(callback));
  } else {
    uint32_t compositor_id = compositor_->id();  // Input destination.
    ui_input::OnEventCallback callback =
        [this, compositor_id](fuchsia::ui::input::InputEvent event) {
          OnDeviceInputEvent(compositor_id, std::move(event));
        };
    state = std::make_unique<ui_input::DeviceState>(
        input_device->id(), input_device->descriptor(), std::move(callback));
  }

  state->OnRegistered();
  device_by_id_.emplace(device_id, std::move(input_device));
  device_state_by_id_.emplace(device_id, std::move(state));
}

void App::OnDeviceDisconnected(ui_input::InputDeviceImpl* input_device) {
  const uint32_t device_id = input_device->id();

  if (device_by_id_.count(device_id) == 0)
    return;

  FXL_VLOG(2) << "DirectInput - UnregisterDevice: " << device_id;

  device_state_by_id_[device_id]->OnUnregistered();
  device_state_by_id_.erase(device_id);
  device_by_id_.erase(device_id);
}

void App::OnReport(ui_input::InputDeviceImpl* input_device,
                   fuchsia::ui::input::InputReport report) {
  const uint32_t device_id = input_device->id();

  if (device_by_id_.count(device_id) == 0)
    return;

  FXL_VLOG(3) << "DirectInput - OnReport: " << device_id << " " << report;

  ui_input::DeviceState* state = device_state_by_id_[device_id].get();
  fuchsia::math::Size size;
  size.width = width_in_px_;
  size.height = height_in_px_;
  state->Update(std::move(report), size);
}

}  // namespace direct_input
