// Copyright 2021 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/lib/focus/focus_manager.h"

#include <lib/syslog/cpp/macros.h>

namespace focus {

namespace {
std::string ToString(const std::vector<zx_koid_t>& chain) {
  std::string value;
  for (zx_koid_t koid : chain) {
    value += std::to_string(koid);
    value += ", ";
  }
  return value;
}
zx_koid_t FocusKoidOf(const std::vector<zx_koid_t>& chain) {
  if (chain.empty()) {
    return ZX_KOID_INVALID;
  }
  return chain.back();
}
}  // namespace

FocusManager::FocusManager(inspect::Node inspect_node, LegacyFocusListener legacy_focus_listener)
    : legacy_focus_listener_(std::move(legacy_focus_listener)),
      view_focuser_registry_(/*request_focus*/ [this](zx_koid_t requestor, zx_koid_t request) {
        return RequestFocus(requestor, request) == FocusChangeStatus::kAccept;
      }),
      inspect_node_(std::move(inspect_node)) {
  // Track the focus chain in inspect.
  lazy_ = inspect_node_.CreateLazyValues("values", [this] {
    inspect::Inspector inspector;

    auto array = inspector.GetRoot().CreateUintArray("focus_chain", focus_chain_.size());
    for (size_t i = 0; i < focus_chain_.size(); i++) {
      array.Set(i, focus_chain_[i]);
    }
    inspector.emplace(std::move(array));

    return fpromise::make_ok_promise(std::move(inspector));
  });
}

void FocusManager::Publish(sys::ComponentContext& component_context) {
  component_context.outgoing()->AddPublicService<FocusChainListenerRegistry>(
      focus_chain_listener_registry_.GetHandler(this));
}

FocusChangeStatus FocusManager::RequestFocus(zx_koid_t requestor, zx_koid_t request) {
  // Invalid requestor.
  if (snapshot_->view_tree.count(requestor) == 0) {
    return FocusChangeStatus::kErrorRequestorInvalid;
  }

  // Invalid request.
  if (snapshot_->view_tree.count(request) == 0) {
    return FocusChangeStatus::kErrorRequestInvalid;
  }

  // Transfer policy: requestor must be authorized.
  if (std::find(focus_chain_.begin(), focus_chain_.end(), requestor) == focus_chain_.end()) {
    return FocusChangeStatus::kErrorRequestorNotAuthorized;
  }

  // Transfer policy: requestor must be ancestor of request
  if (!snapshot_->IsDescendant(/*descendant_koid*/ request, /*ancestor_koid*/ requestor) &&
      request != requestor) {
    return FocusChangeStatus::kErrorRequestorNotRequestAncestor;
  }

  // Transfer policy: request must be focusable
  if (!snapshot_->view_tree.at(request).is_focusable) {
    return FocusChangeStatus::kErrorRequestCannotReceiveFocus;
  }

  // It's a valid request for a change to focus chain.
  SetFocus(request);
  FX_DCHECK(focus_chain_.at(0) == snapshot_->root);
  return FocusChangeStatus::kAccept;
}

void FocusManager::OnNewViewTreeSnapshot(std::shared_ptr<const view_tree::Snapshot> snapshot) {
  FX_DCHECK(snapshot);
  snapshot_ = std::move(snapshot);
  // TODO(fxbug.dev/76138): This has linear cost. Look at making it cheaper.
  // ViewRefFocused clients should be registered before RepairFocus() so that they can be notified
  // about the new root getting focus.
  view_ref_focused_registry_.Update(*snapshot_);
  RepairFocus();
}

void FocusManager::Register(
    fidl::InterfaceHandle<fuchsia::ui::focus::FocusChainListener> focus_chain_listener) {
  const uint64_t id = next_focus_chain_listener_id_++;
  fuchsia::ui::focus::FocusChainListenerPtr new_listener;
  new_listener.Bind(std::move(focus_chain_listener));
  new_listener.set_error_handler([this, id](zx_status_t) { focus_chain_listeners_.erase(id); });
  const auto [_, success] = focus_chain_listeners_.emplace(id, std::move(new_listener));
  FX_DCHECK(success);

  // Dispatch current chain on register.
  DispatchFocusChainTo(focus_chain_listeners_.at(id));
}

void FocusManager::RegisterViewRefFocused(
    zx_koid_t koid, fidl::InterfaceRequest<fuchsia::ui::views::ViewRefFocused> vrf) {
  view_ref_focused_registry_.Register(koid, std::move(vrf));
}

void FocusManager::RegisterViewFocuser(
    zx_koid_t koid, fidl::InterfaceRequest<fuchsia::ui::views::Focuser> focuser) {
  view_focuser_registry_.Register(koid, std::move(focuser));
}

void FocusManager::DispatchFocusChainTo(
    const fuchsia::ui::focus::FocusChainListenerPtr& listener) const {
  listener->OnFocusChange(CloneFocusChain(), [] { /* No flow control yet. */ });
}

void FocusManager::DispatchFocusChain() const {
  for (auto& [_, listener] : focus_chain_listeners_) {
    DispatchFocusChainTo(listener);
  }
}

void FocusManager::DispatchFocusEvents(zx_koid_t old_focus, zx_koid_t new_focus) {
  // Send over fuchsia.ui.scenic.SessionListener ("GFX").
  legacy_focus_listener_(old_focus, new_focus);

  // Send over fuchsia.ui.views.ViewRefFocused.
  view_ref_focused_registry_.UpdateFocus(old_focus, new_focus);
}

fuchsia::ui::views::ViewRef FocusManager::CloneViewRefOf(zx_koid_t koid) const {
  FX_DCHECK(snapshot_->view_tree.count(koid) != 0)
      << "all views in the focus chain must exist in the view tree";
  fuchsia::ui::views::ViewRef clone;
  fidl::Clone(*snapshot_->view_tree.at(koid).view_ref, &clone);
  return clone;
}

fuchsia::ui::focus::FocusChain FocusManager::CloneFocusChain() const {
  fuchsia::ui::focus::FocusChain full_copy{};
  for (const zx_koid_t koid : focus_chain_) {
    full_copy.mutable_focus_chain()->push_back(CloneViewRefOf(koid));
  }
  return full_copy;
}

void FocusManager::RepairFocus() {
  // Old root no longer valid -> move focus to new root.
  if (focus_chain_.empty() || snapshot_->root != focus_chain_.front()) {
    SetFocus(snapshot_->root);
    return;
  }

  std::vector<zx_koid_t> new_focus_chain = focus_chain_;

  // See if there's any place where the old focus chain breaks a parent-child relationship, and
  // truncate from there.
  // Note: Start at i = 1 so we can compare with i - 1.
  for (size_t child_index = 1; child_index < new_focus_chain.size(); ++child_index) {
    const zx_koid_t child = new_focus_chain.at(child_index);
    const zx_koid_t parent = new_focus_chain.at(child_index - 1);
    if (snapshot_->view_tree.count(child) == 0 || snapshot_->view_tree.at(child).parent != parent) {
      new_focus_chain.erase(new_focus_chain.begin() + child_index, new_focus_chain.end());
      break;
    }
  }

  SetFocusChain(std::move(new_focus_chain));
}

void FocusManager::SetFocus(zx_koid_t koid) {
  FX_DCHECK(koid != ZX_KOID_INVALID || koid == snapshot_->root);
  if (koid != ZX_KOID_INVALID) {
    FX_DCHECK(snapshot_->view_tree.count(koid) != 0);
    FX_DCHECK(snapshot_->view_tree.at(koid).is_focusable);
  }

  std::vector<zx_koid_t> new_focus_chain;

  // Regenerate chain.
  while (koid != ZX_KOID_INVALID) {
    new_focus_chain.emplace_back(koid);
    koid = snapshot_->view_tree.at(koid).parent;
  }
  std::reverse(new_focus_chain.begin(), new_focus_chain.end());

  SetFocusChain(std::move(new_focus_chain));
}

void FocusManager::SetFocusChain(std::vector<zx_koid_t> update) {
  if (update != focus_chain_) {
    FX_VLOGS(1) << "Focus chain update: " << ToString(update);
    const zx_koid_t old_focus = FocusKoidOf(focus_chain_);
    const zx_koid_t new_focus = FocusKoidOf(update);

    focus_chain_ = std::move(update);

    DispatchFocusChain();
    DispatchFocusEvents(old_focus, new_focus);
  }
}

}  // namespace focus
