// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
// ┃ ██████ ██████ ██████       █      █      █      █      █ █▄  ▀███ █       ┃
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█  ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄  ▀█ █ ▀▀▀▀▀ ┃
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄   █ ▄▄▄▄▄ ┃
// ┃ █      ██████ █  ▀█▄       █ ██████      █      ███▌▐███ ███████▄ █       ┃
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
// ┃ Copyright (c) 2017, the Perspective Authors.                              ┃
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
// ┃ This file is part of the Perspective library, distributed under the terms ┃
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

import * as d3 from "d3";
import { isElementOverflowing } from "../../utils/utils";
import { getChartElement } from "../../plugin/root";
import { NodeRect, Orient } from "../../types";

export const margin = 10;

export type AdjustedOffsets = {
    x: number;
    y: number;
};

export function enforceContainerBoundaries(
    innerNode: Element,
    offsetX: number,
    offsetY: number
): AdjustedOffsets {
    const chartNodeRect: DOMRect = d3
        .select(getChartElement(innerNode).getContainer())
        .node()
        .getBoundingClientRect();

    const innerNodeRect: NodeRect = innerNode.getBoundingClientRect();

    const draggedInnerNodeRect: NodeRect = {
        top: innerNodeRect.top + offsetY - margin,
        right: innerNodeRect.right + offsetX + margin,
        bottom: innerNodeRect.bottom + offsetY + margin,
        left: innerNodeRect.left + offsetX - margin,
    };

    const adjustedOffsets: AdjustedOffsets = { x: offsetX, y: offsetY };
    const boundaries: { edge: Orient; dimension: "x" | "y" }[] = [
        { edge: "right", dimension: "x" },
        { edge: "left", dimension: "x" },
        { edge: "top", dimension: "y" },
        { edge: "bottom", dimension: "y" },
    ];

    boundaries.forEach((bound) => {
        if (
            isElementOverflowing(
                chartNodeRect,
                draggedInnerNodeRect,
                bound.edge
            )
        ) {
            const adjustment =
                draggedInnerNodeRect[bound.edge] - chartNodeRect[bound.edge];
            adjustedOffsets[bound.dimension] =
                adjustedOffsets[bound.dimension] - adjustment;
        }
    });

    return adjustedOffsets;
}
