// Copyright 2019 The Chromium 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 "ui/accessibility/platform/ax_platform_node_textprovider_win.h"

#include <utility>

#include "base/win/scoped_safearray.h"
#include "ui/accessibility/ax_node_position.h"
#include "ui/accessibility/platform/ax_platform_node_base.h"
#include "ui/accessibility/platform/ax_platform_node_delegate.h"
#include "ui/accessibility/platform/ax_platform_node_textrangeprovider_win.h"

#define UIA_VALIDATE_TEXTPROVIDER_CALL() \
  if (!owner()->GetDelegate())           \
    return UIA_E_ELEMENTNOTAVAILABLE;
#define UIA_VALIDATE_TEXTPROVIDER_CALL_1_ARG(arg) \
  if (!owner()->GetDelegate())                    \
    return UIA_E_ELEMENTNOTAVAILABLE;             \
  if (!arg)                                       \
    return E_INVALIDARG;

namespace ui {

AXPlatformNodeTextProviderWin::AXPlatformNodeTextProviderWin() {
  DVLOG(1) << __func__;
}

AXPlatformNodeTextProviderWin::~AXPlatformNodeTextProviderWin() {}

// static
AXPlatformNodeTextProviderWin* AXPlatformNodeTextProviderWin::Create(
    AXPlatformNodeWin* owner) {
  CComObject<AXPlatformNodeTextProviderWin>* text_provider = nullptr;
  if (SUCCEEDED(CComObject<AXPlatformNodeTextProviderWin>::CreateInstance(
          &text_provider))) {
    DCHECK(text_provider);
    text_provider->owner_ = owner;
    text_provider->AddRef();
    return text_provider;
  }

  return nullptr;
}

// static
void AXPlatformNodeTextProviderWin::CreateIUnknown(AXPlatformNodeWin* owner,
                                                   IUnknown** unknown) {
  Microsoft::WRL::ComPtr<AXPlatformNodeTextProviderWin> text_provider(
      Create(owner));
  if (text_provider)
    *unknown = text_provider.Detach();
}

//
// ITextProvider methods.
//

HRESULT AXPlatformNodeTextProviderWin::GetSelection(SAFEARRAY** selection) {
  WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXT_GETSELECTION);
  UIA_VALIDATE_TEXTPROVIDER_CALL();

  *selection = nullptr;

  AXPlatformNodeDelegate* delegate = owner()->GetDelegate();
  ui::AXTree::Selection unignored_selection = delegate->GetUnignoredSelection();

  AXPlatformNode* anchor_object =
      delegate->GetFromNodeID(unignored_selection.anchor_object_id);
  AXPlatformNode* focus_object =
      delegate->GetFromNodeID(unignored_selection.focus_object_id);

  // anchor_offset corresponds to the selection start index
  // and focus_offset is where the selection ends.
  auto start_offset = unignored_selection.anchor_offset;
  auto end_offset = unignored_selection.focus_offset;

  // If there's no selected object, return success and don't fill the SAFEARRAY.
  if (!anchor_object || !focus_object)
    return S_OK;

  AXNodePosition::AXPositionInstance start =
      anchor_object->GetDelegate()->CreateTextPositionAt(start_offset);
  AXNodePosition::AXPositionInstance end =
      focus_object->GetDelegate()->CreateTextPositionAt(end_offset);

  DCHECK(!start->IsNullPosition());
  DCHECK(!end->IsNullPosition());

  // Reverse start and end if the selection goes backwards
  if (*start > *end)
    std::swap(start, end);

  Microsoft::WRL::ComPtr<ITextRangeProvider> text_range_provider =
      AXPlatformNodeTextRangeProviderWin::CreateTextRangeProvider(
          owner_.Get(), std::move(start), std::move(end));
  if (&text_range_provider == nullptr)
    return E_OUTOFMEMORY;

  // Since we don't support disjoint text ranges, the SAFEARRAY returned
  // will always have one element
  base::win::ScopedSafearray selections_to_return(
      SafeArrayCreateVector(VT_UNKNOWN /* element type */, 0 /* lower bound */,
                            1 /* number of elements */));

  if (!selections_to_return.Get())
    return E_OUTOFMEMORY;

  LONG index = 0;
  HRESULT hr = SafeArrayPutElement(selections_to_return.Get(), &index,
                                   text_range_provider.Get());
  DCHECK(SUCCEEDED(hr));

  // Since DCHECK only happens in debug builds, return immediately to ensure
  // that we're not leaking the SAFEARRAY on release builds
  if (FAILED(hr))
    return E_FAIL;

  *selection = selections_to_return.Release();

  return S_OK;
}

HRESULT AXPlatformNodeTextProviderWin::GetVisibleRanges(
    SAFEARRAY** visible_ranges) {
  WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXT_GETVISIBLERANGES);
  UIA_VALIDATE_TEXTPROVIDER_CALL();

  const AXPlatformNodeDelegate* delegate = owner()->GetDelegate();

  // Get the Clipped Frame Bounds of the current node, not from the root,
  // so if this node is wrapped with overflow styles it will have the
  // correct bounds
  const gfx::Rect frame_rect = delegate->GetBoundsRect(
      AXCoordinateSystem::kFrame, AXClippingBehavior::kClipped);

  const auto start = delegate->CreateTextPositionAt(0);
  const auto end = start->CreatePositionAtEndOfAnchor();
  DCHECK(start->GetAnchor() == end->GetAnchor());

  // SAFEARRAYs are not dynamic, so fill the visible ranges in a vector
  // and then transfer to an appropriately-sized SAFEARRAY
  std::vector<Microsoft::WRL::ComPtr<ITextRangeProvider>> ranges;

  auto current_line_start = start->Clone();
  while (!current_line_start->IsNullPosition() && *current_line_start < *end) {
    auto current_line_end = current_line_start->CreateNextLineEndPosition(
        AXBoundaryBehavior::CrossBoundary);
    if (current_line_end->IsNullPosition() || *current_line_end > *end)
      current_line_end = end->Clone();

    gfx::Rect current_rect = delegate->GetInnerTextRangeBoundsRect(
        current_line_start->text_offset(), current_line_end->text_offset(),
        AXCoordinateSystem::kFrame, AXClippingBehavior::kUnclipped);

    if (frame_rect.Contains(current_rect)) {
      Microsoft::WRL::ComPtr<ITextRangeProvider> text_range_provider =
          AXPlatformNodeTextRangeProviderWin::CreateTextRangeProvider(
              owner_.Get(), current_line_start->Clone(),
              current_line_end->Clone());

      ranges.emplace_back(text_range_provider);
    }

    current_line_start = current_line_start->CreateNextLineStartPosition(
        AXBoundaryBehavior::CrossBoundary);
  }

  base::win::ScopedSafearray scoped_visible_ranges(
      SafeArrayCreateVector(VT_UNKNOWN /* element type */, 0 /* lower bound */,
                            ranges.size() /* number of elements */));

  if (!scoped_visible_ranges.Get())
    return E_OUTOFMEMORY;

  LONG index = 0;
  for (Microsoft::WRL::ComPtr<ITextRangeProvider>& current_provider : ranges) {
    HRESULT hr = SafeArrayPutElement(scoped_visible_ranges.Get(), &index,
                                     current_provider.Get());
    DCHECK(SUCCEEDED(hr));

    // Since DCHECK only happens in debug builds, return immediately to ensure
    // that we're not leaking the SAFEARRAY on release builds
    if (FAILED(hr))
      return E_FAIL;

    ++index;
  }

  *visible_ranges = scoped_visible_ranges.Release();

  return S_OK;
}

HRESULT AXPlatformNodeTextProviderWin::RangeFromChild(
    IRawElementProviderSimple* child,
    ITextRangeProvider** range) {
  WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXT_RANGEFROMCHILD);
  UIA_VALIDATE_TEXTPROVIDER_CALL_1_ARG(child);

  *range = nullptr;

  Microsoft::WRL::ComPtr<ui::AXPlatformNodeWin> child_platform_node;
  if (!SUCCEEDED(child->QueryInterface(IID_PPV_ARGS(&child_platform_node))))
    return UIA_E_INVALIDOPERATION;

  if (!owner()->IsDescendant(child_platform_node.Get()))
    return E_INVALIDARG;

  *range = GetRangeFromChild(owner(), child_platform_node.Get());

  return S_OK;
}

HRESULT AXPlatformNodeTextProviderWin::RangeFromPoint(
    UiaPoint uia_point,
    ITextRangeProvider** range) {
  WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXT_RANGEFROMPOINT);
  WIN_ACCESSIBILITY_API_PERF_HISTOGRAM(UMA_API_TEXT_RANGEFROMPOINT);
  UIA_VALIDATE_TEXTPROVIDER_CALL();
  *range = nullptr;

  gfx::Point point(uia_point.x, uia_point.y);
  // Retrieve the closest accessibility node. No coordinate unit conversion is
  // needed, hit testing input is also in screen coordinates.

  AXPlatformNodeWin* nearest_node =
      static_cast<AXPlatformNodeWin*>(owner()->NearestLeafToPoint(point));
  DCHECK(nearest_node);
  DCHECK(nearest_node->IsLeaf());

  AXNodePosition::AXPositionInstance start, end;
  start = nearest_node->GetDelegate()->CreateTextPositionAt(
      nearest_node->NearestTextIndexToPoint(point));
  DCHECK(!start->IsNullPosition());
  end = start->Clone();

  *range = AXPlatformNodeTextRangeProviderWin::CreateTextRangeProvider(
      nearest_node, std::move(start), std::move(end));
  return S_OK;
}

HRESULT AXPlatformNodeTextProviderWin::get_DocumentRange(
    ITextRangeProvider** range) {
  WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXT_GET_DOCUMENTRANGE);
  UIA_VALIDATE_TEXTPROVIDER_CALL();

  // Get range from child, where child is the current node. In other words,
  // getting the text range of the current owner AxPlatformNodeWin node.
  *range = GetRangeFromChild(owner(), owner());

  return S_OK;
}

HRESULT AXPlatformNodeTextProviderWin::get_SupportedTextSelection(
    enum SupportedTextSelection* text_selection) {
  WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXT_GET_SUPPORTEDTEXTSELECTION);
  UIA_VALIDATE_TEXTPROVIDER_CALL();

  *text_selection = SupportedTextSelection_Single;
  return S_OK;
}

//
// ITextEditProvider methods.
//

HRESULT AXPlatformNodeTextProviderWin::GetActiveComposition(
    ITextRangeProvider** range) {
  WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXTEDIT_GETACTIVECOMPOSITION);
  UIA_VALIDATE_TEXTPROVIDER_CALL();

  *range = nullptr;
  return GetTextRangeProviderFromActiveComposition(range);
}

HRESULT AXPlatformNodeTextProviderWin::GetConversionTarget(
    ITextRangeProvider** range) {
  WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXTEDIT_GETCONVERSIONTARGET);
  UIA_VALIDATE_TEXTPROVIDER_CALL();

  *range = nullptr;
  return GetTextRangeProviderFromActiveComposition(range);
}

ITextRangeProvider* AXPlatformNodeTextProviderWin::GetRangeFromChild(
    ui::AXPlatformNodeWin* ancestor,
    ui::AXPlatformNodeWin* descendant) {
  DCHECK(ancestor);
  DCHECK(descendant);
  DCHECK(descendant->GetDelegate());
  DCHECK(ancestor->IsDescendant(descendant));

  // Start and end should be leaf text positions that span the beginning and end
  // of text content within a node. The start position should be the directly
  // first child and the end position should be the deepest last child node.
  AXNodePosition::AXPositionInstance start =
      descendant->GetDelegate()->CreateTextPositionAt(0)->AsLeafTextPosition();

  AXNodePosition::AXPositionInstance end;
  if (ui::IsDocument(descendant->GetData().role)) {
    // Fast path for getting the range of the web root.
    end = start->CreatePositionAtEndOfDocument();
  } else if (descendant->GetChildCount() == 0) {
    end = descendant->GetDelegate()
              ->CreateTextPositionAt(0)
              ->CreatePositionAtEndOfAnchor()
              ->AsLeafTextPosition();
  } else {
    AXPlatformNodeBase* deepest_last_child = descendant->GetLastChild();
    while (deepest_last_child && deepest_last_child->GetChildCount() > 0)
      deepest_last_child = deepest_last_child->GetLastChild();

    end = deepest_last_child->GetDelegate()
              ->CreateTextPositionAt(0)
              ->CreatePositionAtEndOfAnchor()
              ->AsLeafTextPosition();
  }

  return AXPlatformNodeTextRangeProviderWin::CreateTextRangeProvider(
      ancestor, std::move(start), std::move(end));
}

ui::AXPlatformNodeWin* AXPlatformNodeTextProviderWin::owner() const {
  return owner_.Get();
}

HRESULT
AXPlatformNodeTextProviderWin::GetTextRangeProviderFromActiveComposition(
    ITextRangeProvider** range) {
  *range = nullptr;
  // We fetch the start and end offset of an active composition only if
  // this object has focus and TSF is in composition mode.
  // The offsets here refer to the character positions in a plain text
  // view of the DOM tree. Ex: if the active composition in an element
  // has "abc" then the range will be (0,3) in both TSF and accessibility
  if ((AXPlatformNode::FromNativeViewAccessible(
           owner()->GetDelegate()->GetFocus()) ==
       static_cast<AXPlatformNode*>(owner())) &&
      owner()->HasActiveComposition()) {
    gfx::Range active_composition_offset =
        owner()->GetActiveCompositionOffsets();
    AXNodePosition::AXPositionInstance start =
        owner()->GetDelegate()->CreateTextPositionAt(
            /*offset*/ active_composition_offset.start());
    AXNodePosition::AXPositionInstance end =
        owner()->GetDelegate()->CreateTextPositionAt(
            /*offset*/ active_composition_offset.end());

    *range = AXPlatformNodeTextRangeProviderWin::CreateTextRangeProvider(
        owner_.Get(), std::move(start), std::move(end));
  }

  return S_OK;
}

}  // namespace ui
