import {FirstRenderedNodeData, RendererNode, RendererNodeType} from "./RendererNodeData";
import {TreeNode} from "./TreeNode";
import {StateBranchNode} from "./StateBranchNode";
import {GeneralHelpers} from "@xyflow/react";
import {getNode} from "./store";
import {getDimensions} from "../Tree";

export class TreeNodeAnchor implements RendererNode, FirstRenderedNodeData {
    constructor(public treeNode: TreeNode) {}

    getId(): string {
        return this.treeNode.id;
    }

    /**
     * Its target is always the testable node of the tree node it belongs to
     */
    getTargetRenderNode(): RendererNodeType | undefined {
        return this.treeNode.testableNode
    }

    /**
     * Its source is the previous tree node's source anchor, unless it's the first tree node in the grove in which case it has no source
     */
    getSourceRenderNode(): RendererNodeType | undefined {
        /**
         * This probably violates the Law of Demeter pretty badly but it will have to do srry.-
         */
        if (this.treeNode.grove.isFirst(this.treeNode.id)) {
            return undefined;
        }

        return this.treeNode.grove.getPreviousTreeNode(this.treeNode.id)?.sourceAnchor as RendererNodeType
    }

    treeNodeForCalculatingFullWidth(): TreeNode | undefined {
        return (this.getTargetRenderNode() as StateBranchNode).getTreeNode()
    }

    /**
     * The source x here needs to be 0 because we're getting it from the x and width of the source,
     * we need to explicitly set to 0 to tell the engine that we don't want any extra x
     * (in tiers,in their respective node classes, for example, this method returns undefined to tell the engine to use the source's x)
     */
    horizontalSourceX(getNode: GeneralHelpers["getNode"]): number | undefined {
        return 0
    }

    /**
     * Since this anchor is horizontally centered and its tiny, we need to calculate half of this tree's root testable so that it is aligned property
     */
    leftSpacing(): number {
        const {width} = getDimensions((this.getTargetRenderNode()!.getId())) || {width: 0, height: 0};

        const leftSpacing = 60
        
        return Math.max((width / 2), 0) + leftSpacing
    }


    getTargetRenderNodeId(): string {
        return this.getTargetRenderNode()!.getId()
    }

    getSourceRenderNodeId(): string {
        return this.getSourceRenderNode()?.getId() || ''
    }
}