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

#include <limits>
#include <string>

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

#include "src/lib/fxl/logging.h"
#include "lib/ui/input/cpp/formatting.h"
#include "lib/ui/scenic/cpp/resources.h"

namespace direct_input_child {

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

App::App(async::Loop* loop)
    : startup_context_(component::StartupContext::CreateFromStartupInfo()),
      message_loop_(loop),
      focused_(false),
      view_provider_binding_(this) {
  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) << "Child - connect to Scenic.";

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

  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());
  });

  startup_context_->outgoing()
      .deprecated_services()
      ->AddService<fuchsia::ui::app::ViewProvider>(
          [this](
              fidl::InterfaceRequest<fuchsia::ui::app::ViewProvider> request) {
            view_provider_binding_.Bind(std::move(request));
          },
          "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) << "Child - ViewProvider service set up.";
}

App::~App() {
  startup_context_->outgoing()
      .deprecated_services()
      ->RemoveService<fuchsia::ui::app::ViewProvider>();
  ReleaseSessionResources();
}

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

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

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

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

void App::OnSessionClose() {
  FXL_LOG(INFO) << "Child - 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) << "Child - 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::CreateView(
    zx::eventpair view_token,
    fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> incoming_services,
    fidl::InterfaceHandle<fuchsia::sys::ServiceProvider> outgoing_services) {
  FXL_LOG(INFO) << "Child - CreateView invoked.";
  view_ = std::make_unique<scenic::View>(session_.get(), std::move(view_token),
                                         "child view");
  view_->SetLabel("child view");

  if (root_node_) {
    view_->AddChild(*root_node_);
    FXL_LOG(INFO) << "Child - outbound view is set up.";
  }
}

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) << "Child - display size: " << display_width << ", "
                << display_height;

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

  auto session = session_.get();

  const float kMargin = 100.f;
  const float kWidth = display_width - 6.f * kMargin;
  const float kHeight = display_height - 6.f * kMargin;

  // Set up root node, expose it to outbound View.
  {
    std::unique_ptr<scenic::EntityNode> root_node =
        std::make_unique<scenic::EntityNode>(session);
    root_node->SetLabel("child root node");
    root_node->SetTranslation(0.f, 0.f, -100.f);

    scenic::ShapeNode shape(session);
    scenic::Rectangle rec(session, kWidth, kHeight);
    shape.SetShape(rec);
    scenic::Material material(session);
    material.SetColor(0, 191, 255, 255);  // Light blue
    shape.SetMaterial(material);
    root_node->AddPart(shape);

    if (view_) {
      view_->AddChild(*root_node);
      FXL_LOG(INFO) << "Child - outbound view is set up.";
    }

    root_node_ = std::move(root_node);
    FXL_LOG(INFO) << "Child - root node is set up.";
  }

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

    const float kElevation = 110.f;  // Z height
    const float kBar = 50.f;
    const float kTranslateX = (kWidth - kBar) * 0.5f;
    const float kTranslateY = (kHeight - kBar) * 0.5f;

    scenic::Material material(session);
    material.SetColor(0, 0, 255, 255);  // Blue
    scenic::Rectangle horizontal_bar(session, kWidth, kBar);
    scenic::Rectangle vertical_bar(session, kBar, kHeight);

    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) << "Child - 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(0, 0, 255, 255);  // Blue
      pointer_tracker_[i]->SetMaterial(material);
    }

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

}  // namespace direct_input_child
