// 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/hello_input/app.h"

#include <limits>
#include <string>

#include <fuchsia/math/cpp/fidl.h>
#include <lib/fdio/util.h>
#include <lib/fit/function.h>
#include <lib/zx/time.h>

#include "lib/ui/input/cpp/formatting.h"
#include "lib/ui/scenic/cpp/resources.h"
#include "lib/ui/scenic/fidl_helpers.h"

// Lifted from hello_views.
static fuchsia::sys::FileDescriptorPtr CloneFileDescriptor(int fd) {
  zx_handle_t handles[FDIO_MAX_HANDLES] = {0, 0, 0};
  uint32_t types[FDIO_MAX_HANDLES] = {
      ZX_HANDLE_INVALID,
      ZX_HANDLE_INVALID,
      ZX_HANDLE_INVALID,
  };
  zx_status_t status = fdio_clone_fd(fd, 0, handles, types);
  if (status <= 0) {
    return nullptr;
  }
  fuchsia::sys::FileDescriptorPtr result = fuchsia::sys::FileDescriptor::New();
  result->type0 = types[0];
  result->handle0 = zx::handle(handles[0]);
  result->type1 = types[1];
  result->handle1 = zx::handle(handles[1]);
  result->type2 = types[2];
  result->handle2 = zx::handle(handles[2]);
  return result;
}

namespace examples_ui_hello_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) << "HelloInput - scenic connection";

  session_ = std::make_unique<scenic::Session>(scenic_.get());
  session_->SetDebugName("Hello 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) << "HelloInput - session set up";

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

  input_reader_.Start();
  startup_context_->outgoing().AddPublicService(
      input_device_registry_bindings_.GetHandler(this));
  FXL_LOG(INFO) << "HelloInput - 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(ZX_CLOCK_MONOTONIC));
  });

  {
    component::Services child_services;
    fuchsia::sys::LaunchInfo launch_info;
    launch_info.out = CloneFileDescriptor(STDOUT_FILENO);
    launch_info.err = CloneFileDescriptor(STDERR_FILENO);
    launch_info.url =
        "fuchsia-pkg://fuchsia.com/hello_input_child#meta/"
        "hello_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) << "HelloInput - 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) << "HelloInput - shutting down.";
      child_controller_->Kill();
      async::PostTask(message_loop_->dispatcher(),
                      [this]() { OnSessionClose(); });
    }
  }
}

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

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

void App::OnSessionClose() {
  FXL_LOG(INFO) << "HelloInput - 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) << "HelloInput - 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) << "HelloInput - 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) << "HelloInput - 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) << "HelloInput - root node is set up.";
  }

  // Create View/ViewHolder. Attach ViewHolder to root node.
  {
    zx::eventpair view_token;
    zx::eventpair view_holder_token;
    zx_status_t status =
        zx::eventpair::create(/*flags*/ 0u, &view_holder_token, &view_token);
    FXL_CHECK(status == ZX_OK)
        << "Failed to create eventpair for view/viewholder.";

    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) << "HelloInput - 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) << "HelloInput - 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) << "HelloInput - 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) << "HelloInput - 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) << "HelloInput - child view requested, view holder set up.";
  }
}

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

void App::OnDeviceInputEvent(uint32_t compositor_id,
                             fuchsia::ui::input::InputEvent event) {
  FXL_VLOG(1) << "HelloInput - 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) << "HelloInput - RegisterDevice: " << device_id << " "
              << descriptor;
  std::unique_ptr<mozart::InputDeviceImpl> input_device =
      std::make_unique<mozart::InputDeviceImpl>(
          device_id, std::move(descriptor), std::move(input_device_request),
          this);

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

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

  FXL_VLOG(2) << "HelloInput - 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(mozart::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) << "HelloInput - OnReport: " << device_id << " " << report;

  mozart::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 examples_ui_hello_input
