// Copyright 2019 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/a11y/lib/screen_reader/util/util.h"

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

#include <algorithm>
#include <string>
#include <vector>

#include "fuchsia/accessibility/semantics/cpp/fidl.h"

namespace a11y {

namespace {

bool NodeHasSubsetOfActions(const fuchsia::accessibility::semantics::Node* node_1,
                            const fuchsia::accessibility::semantics::Node* node_2) {
  // If node_1 doesn't have any actions, then by definition, its actions must be
  // a subset of node_2's actions.
  if (!node_1->has_actions() || node_1->actions().empty()) {
    return true;
  }

  // If node_1 does have actions, and node_2 doesn't, then node_1's actions are
  // not a subset of node_2's.
  if (!node_2->has_actions() || node_2->actions().empty()) {
    return false;
  }

  const auto& node_1_actions = node_1->actions();
  const auto& node_2_actions = node_2->actions();

  // If node_1 contains more actions than node_2, then its actions cannot be a
  // subset of node_2's.
  if (node_1_actions.size() > node_2_actions.size()) {
    return false;
  }

  std::set<fuchsia::accessibility::semantics::Action> node_2_actions_set(node_2_actions.begin(),
                                                                         node_2_actions.end());

  for (const auto node_1_action : node_1_actions) {
    // If node_1 has an action that node_2 does not, then node_1's actions are
    // not a subset of node_2's.
    if (node_2_actions_set.find(node_1_action) == node_2_actions_set.end()) {
      return false;
    }
  }

  return true;
}

}  // namespace

bool IsContainer(const fuchsia::accessibility::semantics::Node* node) {
  return node->has_role() && (node->role() == fuchsia::accessibility::semantics::Role::TABLE ||
                              node->role() == fuchsia::accessibility::semantics::Role::LIST);
}

bool NodeIsDescribable(const fuchsia::accessibility::semantics::Node* node) {
  if (!node) {
    return false;
  }
  if (node->has_states() && node->states().has_hidden() && node->states().hidden()) {
    return false;
  }

  bool contains_text = node->has_attributes() && node->attributes().has_label() &&
                       !node->attributes().label().empty();
  bool is_actionable =
      node->has_role() && (node->role() == fuchsia::accessibility::semantics::Role::BUTTON ||
                           node->role() == fuchsia::accessibility::semantics::Role::TOGGLE_SWITCH ||
                           node->role() == fuchsia::accessibility::semantics::Role::RADIO_BUTTON ||
                           node->role() == fuchsia::accessibility::semantics::Role::LINK ||
                           node->role() == fuchsia::accessibility::semantics::Role::CHECK_BOX ||
                           node->role() == fuchsia::accessibility::semantics::Role::SLIDER ||
                           node->role() == fuchsia::accessibility::semantics::Role::IMAGE ||
                           node->role() == fuchsia::accessibility::semantics::Role::CELL ||
                           node->role() == fuchsia::accessibility::semantics::Role::COLUMN_HEADER ||
                           node->role() == fuchsia::accessibility::semantics::Role::ROW_HEADER);

  return (contains_text || is_actionable) && !IsContainer(node);
}

std::vector<const fuchsia::accessibility::semantics::Node*> GetContainerNodes(
    zx_koid_t koid, uint32_t node_id, SemanticsSource* semantics_source) {
  std::vector<const fuchsia::accessibility::semantics::Node*> result;

  const fuchsia::accessibility::semantics::Node* node =
      semantics_source->GetParentNode(koid, node_id);
  while (node) {
    if (IsContainer(node)) {
      result.push_back(node);
    }
    node = semantics_source->GetParentNode(koid, node->node_id());
  }

  // We reverse the result to get 'deepest-last' order.
  std::reverse(result.begin(), result.end());
  return result;
}

std::string FormatFloat(float input) {
  auto output = std::to_string(input);
  FX_DCHECK(!output.empty());

  // If the output string does not contain a decimal point, we don't need to
  // trim trailing zeros.
  auto location_of_decimal = output.find('.');
  if (location_of_decimal == std::string::npos) {
    return output;
  }

  auto location_of_last_non_zero_character = output.find_last_not_of('0');
  // If the last non-zero character is a decimal point, the value is an integer,
  // so we should remove the decimal point and trailing zeros.
  if (location_of_last_non_zero_character == location_of_decimal) {
    return output.erase(location_of_decimal, std::string::npos);
  }

  // If the last digit is non-zero, the string has no trailing zeros, so return
  // the string as is.
  if (location_of_last_non_zero_character == output.size() - 1) {
    return output;
  }

  // In the last remaining case, the string represents a decimal with trailing
  // zeros.
  return output.erase(location_of_last_non_zero_character + 1, std::string::npos);
}

bool SameInformationAsParent(const fuchsia::accessibility::semantics::Node* node,
                             const fuchsia::accessibility::semantics::Node* parent_node) {
  FX_DCHECK(node) << "Node should not be null";

  if (!parent_node) {
    return false;
  }

  if (!node->has_attributes() || !node->attributes().has_label() ||
      node->attributes().label().empty()) {
    return false;
  }
  if (!parent_node->has_attributes() || !parent_node->attributes().has_label() ||
      parent_node->attributes().label().empty()) {
    return false;
  }

  if (node->attributes().label() != parent_node->attributes().label()) {
    return false;
  }

  if (!NodeIsDescribable(parent_node)) {
    return false;
  }

  if (parent_node->has_child_ids() && parent_node->child_ids().size() != 1) {
    return false;
  }

  if (!NodeHasSubsetOfActions(node, parent_node)) {
    return false;
  }

  return true;
}

bool NodeIsSlider(const fuchsia::accessibility::semantics::Node* node) {
  FX_DCHECK(node);

  bool has_role_slider =
      node->has_role() && node->role() == fuchsia::accessibility::semantics::Role::SLIDER;
  bool has_range_value = node->has_states() && node->states().has_range_value();

  return has_role_slider || has_range_value;
}

std::string GetSliderValue(const fuchsia::accessibility::semantics::Node& node) {
  if (!node.has_states()) {
    return std::string();
  }

  if (node.states().has_range_value()) {
    return std::to_string(static_cast<int>((node.states().range_value())));
  }

  if (node.states().has_value() && !node.states().value().empty()) {
    return node.states().value();
  }

  return std::string();
}

}  // namespace a11y
