import type { Node } from '@xyflow/svelte';
import type { CustomNode, TinyflowOptions } from '../types';

export const DEFAULT_NODE_DRAG_HANDLE = '.tf-node-drag-handle';

export type TinyflowNodeNormalizer = (node: Node) => Node;

function shouldUseDefaultDragHandle(
  node: Node,
  customNodes?: Record<string, CustomNode>,
) {
  if (Object.prototype.hasOwnProperty.call(node, 'dragHandle')) {
    return false;
  }
  const customNode = node.type ? customNodes?.[node.type] : undefined;
  return customNode?.presentation !== 'plain';
}

export function createTinyflowNodeNormalizer(
  options?: TinyflowOptions,
): TinyflowNodeNormalizer {
  const readonly = options?.readonly === true;
  const nodesDraggable = options?.nodesDraggable ?? !readonly;
  const nodesConnectable = options?.nodesConnectable ?? !readonly;
  const elementsSelectable = options?.elementsSelectable ?? !readonly;

  return (node) => {
    const nextNode = { ...node };

    if (nodesDraggable) {
      if (nextNode.draggable === false) {
        delete nextNode.draggable;
      }
      if (shouldUseDefaultDragHandle(nextNode, options?.customNodes)) {
        nextNode.dragHandle = DEFAULT_NODE_DRAG_HANDLE;
      }
    } else {
      nextNode.draggable = false;
    }

    if (nodesConnectable) {
      if (nextNode.connectable === false) {
        delete nextNode.connectable;
      }
    } else {
      nextNode.connectable = false;
    }

    if (elementsSelectable) {
      if (nextNode.selectable === false) {
        delete nextNode.selectable;
      }
    } else {
      nextNode.selectable = false;
    }

    return nextNode;
  };
}
