import { useRef } from "react";
import { invariant } from "../../invariant";
import { isInteger } from "../../native-with-fallback";
import checkIsValidInnerRef from "../check-is-valid-inner-ref";
import findDragHandle from "../get-elements/find-drag-handle";
import useDevSetupWarning from "../use-dev-setup-warning";
import useDev from "../use-dev";

export function useValidation(props, contextId, getRef) {
  // running after every update in development
  useDevSetupWarning(() => {
    function prefix(id) {
      return `Draggable[id: ${id}]: `;
    }

    // wrapping entire block for better minification
    const id = props.draggableId;
    invariant(id, "Draggable requires a draggableId");
    invariant(
      typeof id === "string",
      `Draggable requires a [string] draggableId.
      Provided: [type: ${typeof id}] (value: ${id})`
    );
    invariant(isInteger(props.index), `${prefix(id)} requires an integer index prop`);
    if (props.mapped.type === "DRAGGING") {
      return;
    }

    // Checking provided ref (only when not dragging as it might be removed)
    checkIsValidInnerRef(getRef());

    // Checking that drag handle is provided
    // Only running check when enabled.
    // When not enabled there is no drag handle props
    if (props.isEnabled) {
      invariant(findDragHandle(contextId, id), `${prefix(id)} Unable to find drag handle`);
    }
  });
}

// we expect isClone not to change for entire component's life
export function useClonePropValidation(isClone) {
  useDev(() => {
    const initialRef = useRef(isClone);

    useDevSetupWarning(() => {
      invariant(isClone === initialRef.current, "Draggable isClone prop value changed during component life");
    }, [isClone]);
  });
}
