/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#pragma once

#include <react/renderer/components/root/RootShadowNode.h>
#include <react/renderer/core/ShadowNode.h>
#include <cstdint>
#include <string>
#include <tuple>
#include <vector>

namespace facebook::react::dom {

struct DOMRect {
  double x = 0;
  double y = 0;
  double width = 0;
  double height = 0;
};

struct RNMeasureRect {
  double x = 0;
  double y = 0;
  double width = 0;
  double height = 0;
  double pageX = 0;
  double pageY = 0;
};

struct DOMOffset {
  ShadowNode::Shared offsetParent = nullptr;
  double top = 0;
  double left = 0;
};

struct DOMPoint {
  double x = 0;
  double y = 0;
};

struct DOMSizeRounded {
  int width = 0;
  int height = 0;
};

struct DOMBorderWidthRounded {
  int top = 0;
  int right = 0;
  int bottom = 0;
  int left = 0;
};

ShadowNode::Shared getParentNode(
    const RootShadowNode::Shared& currentRevision,
    const ShadowNode& shadowNode);

std::vector<ShadowNode::Shared> getChildNodes(
    const RootShadowNode::Shared& currentRevision,
    const ShadowNode& shadowNode);

bool isConnected(
    const RootShadowNode::Shared& currentRevision,
    const ShadowNode& shadowNode);

uint_fast16_t compareDocumentPosition(
    const RootShadowNode::Shared& currentRevision,
    const ShadowNode& shadowNode,
    const ShadowNode& otherShadowNode);

std::string getTextContent(
    const RootShadowNode::Shared& currentRevision,
    const ShadowNode& shadowNode);

DOMRect getBoundingClientRect(
    const RootShadowNode::Shared& currentRevision,
    const ShadowNode& shadowNode,
    bool includeTransform);

DOMOffset getOffset(
    const RootShadowNode::Shared& currentRevision,
    const ShadowNode& shadowNode);

DOMPoint getScrollPosition(
    const RootShadowNode::Shared& currentRevision,
    const ShadowNode& shadowNode);

DOMSizeRounded getScrollSize(
    const RootShadowNode::Shared& currentRevision,
    const ShadowNode& shadowNode);

DOMSizeRounded getInnerSize(
    const RootShadowNode::Shared& currentRevision,
    const ShadowNode& shadowNode);

DOMBorderWidthRounded getBorderWidth(
    const RootShadowNode::Shared& currentRevision,
    const ShadowNode& shadowNode);

std::string getTagName(const ShadowNode& shadowNode);

// Non-standard methods from React Native

RNMeasureRect measure(
    const RootShadowNode::Shared& currentRevision,
    const ShadowNode& shadowNode);

DOMRect measureInWindow(
    const RootShadowNode::Shared& currentRevision,
    const ShadowNode& shadowNode);

// This method returns an optional to signal to go through the error callback
// instead of going through the success callback with an empty DOMRect.
std::optional<DOMRect> measureLayout(
    const RootShadowNode::Shared& currentRevision,
    const ShadowNode& shadowNode,
    const ShadowNode& relativeToShadowNode);

} // namespace facebook::react::dom
