/*
 * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
 * Copyright (C) 2009 Antonio Gomes <tonikitoo@webkit.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_SPATIAL_NAVIGATION_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_SPATIAL_NAVIGATION_H_

#include "third_party/blink/public/platform/web_focus_type.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"

#include <limits>

namespace blink {

class LocalFrame;
class HTMLAreaElement;
class HTMLFrameOwnerElement;

enum class SpatialNavigationDirection { kNone, kUp, kRight, kDown, kLeft };

inline double MaxDistance() {
  return std::numeric_limits<double>::max();
}

inline int FudgeFactor() {
  return 2;
}

CORE_EXPORT bool IsSpatialNavigationEnabled(const LocalFrame*);
bool SpatialNavigationIgnoresEventHandlers(const LocalFrame*);

struct FocusCandidate {
  STACK_ALLOCATED();

 public:
  FocusCandidate()
      : visible_node(nullptr),
        focusable_node(nullptr),
        enclosing_scrollable_box(nullptr),
        distance(MaxDistance()),
        is_offscreen(true),
        is_offscreen_after_scrolling(true) {}

  FocusCandidate(Node*, SpatialNavigationDirection);
  explicit FocusCandidate(HTMLAreaElement*, SpatialNavigationDirection);
  bool IsNull() const { return !visible_node; }
  bool InScrollableContainer() const {
    return visible_node && enclosing_scrollable_box;
  }
  bool IsFrameOwnerElement() const {
    return visible_node && visible_node->IsFrameOwnerElement();
  }
  Document* GetDocument() const {
    return visible_node ? &visible_node->GetDocument() : nullptr;
  }

  // We handle differently visibleNode and FocusableNode to properly handle the
  // areas of imagemaps, where visibleNode would represent the image element and
  // focusableNode would represent the area element.  In all other cases,
  // visibleNode and focusableNode are one and the same.
  Member<Node> visible_node;
  Member<Node> focusable_node;
  Member<Node> enclosing_scrollable_box;
  double distance;
  LayoutRect rect_in_root_frame;
  bool is_offscreen;
  bool is_offscreen_after_scrolling;
};

CORE_EXPORT bool HasRemoteFrame(const Node*);
CORE_EXPORT bool IsOffscreen(const Node*);
CORE_EXPORT bool IsOffscreenAfterFrameScroll(const Node*,
                                             SpatialNavigationDirection);
bool ScrollInDirection(Node* container, SpatialNavigationDirection);
CORE_EXPORT bool IsScrollableNode(const Node* node);
CORE_EXPORT bool IsScrollableAreaOrDocument(const Node*);
CORE_EXPORT Node* ScrollableAreaOrDocumentOf(Node*);
bool CanScrollInDirection(const Node* container, SpatialNavigationDirection);
bool CanScrollInDirection(const LocalFrame*, SpatialNavigationDirection);
bool AreElementsOnSameLine(const FocusCandidate& first_candidate,
                           const FocusCandidate& second_candidate);
void DistanceDataForNode(SpatialNavigationDirection,
                         const FocusCandidate& current,
                         FocusCandidate&);
CORE_EXPORT LayoutRect NodeRectInRootFrame(const Node*,
                                           bool ignore_border = false);
CORE_EXPORT LayoutRect OppositeEdge(SpatialNavigationDirection side,
                                    const LayoutRect& box,
                                    LayoutUnit thickness = LayoutUnit());
CORE_EXPORT LayoutRect RootViewport(const LocalFrame*);
LayoutRect StartEdgeForAreaElement(const HTMLAreaElement&,
                                   SpatialNavigationDirection);
HTMLFrameOwnerElement* FrameOwnerElement(FocusCandidate&);
CORE_EXPORT LayoutRect SearchOrigin(const LayoutRect,
                                    Node*,
                                    const SpatialNavigationDirection);

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_SPATIAL_NAVIGATION_H_
