import * as React from "react";
import { useContentMemo } from "../../hooks/useContentMemo.js";
import { keyStringFromKeyChain, isArrayValue, valueByKeyChain } from "../utils/keyChain.js";
import { touchedStateForKeyChain } from "../utils/touchedState.js";
import { validationErrorsByKeyChain } from "../utils/validation.js";
const useFormBase = (formStateLive, formStateRef, dispatch, clientValidationErrors, clientValidationDispatcher, touchedState, touchedStateRef, touchedStateDispatcher, parseValidationSchema, initialDataObject, formConfigObject, globalTouchOverride, parentKeyChain) => {
  var _a;
  const formConfig = useContentMemo(formConfigObject);
  const initialData = useContentMemo(initialDataObject);
  const [isGlobalTouched, setGlobalTouched] = React.useState(globalTouchOverride ?? false);
  const set = React.useCallback((keyChain, newValue) => {
    if (keyChain.length === 1) {
      dispatch({
        type: "set-one",
        propertyKey: keyChain[0],
        value: newValue
      });
    } else {
      dispatch({ type: "set-path", keyChain, value: newValue });
    }
  }, [dispatch]);
  React.useEffect(() => {
    setGlobalTouched(globalTouchOverride ?? false);
  }, [globalTouchOverride]);
  const addValidationError = React.useCallback((...errors) => {
    clientValidationDispatcher({ type: "add-validation", errors });
  }, [clientValidationDispatcher]);
  const addValidationErrorFromKeyChain = React.useCallback((keyChain, messages, identifier) => {
    const messageArray = Array.isArray(messages) ? messages : [messages];
    const key = keyStringFromKeyChain(keyChain, "dots");
    addValidationError(...messageArray.map((message) => ({ key, message, identifier })));
  }, [addValidationError]);
  const clearClientValidationErrors = React.useCallback((...identifiers) => {
    clientValidationDispatcher({
      type: "clear-validation",
      identifiers: identifiers.length ? identifiers : void 0
    });
  }, [clientValidationDispatcher]);
  const clearValidationErrorsByKeyChain = React.useCallback((keyChain, identifiers) => {
    const dotKey = keyStringFromKeyChain(keyChain, "dots");
    const bracketKey = keyStringFromKeyChain(keyChain, "brackets");
    clientValidationDispatcher({
      type: "clear-validation",
      key: dotKey,
      identifiers
    });
    clientValidationDispatcher({
      type: "clear-validation",
      key: bracketKey,
      identifiers
    });
  }, [clientValidationDispatcher]);
  const add = React.useCallback((keyChain, currentValue, newItem) => {
    if (isArrayValue(currentValue, "formProp.add")) {
      const newValue = [...currentValue ?? []];
      newValue.push(newItem);
      dispatch({ type: "set-path", keyChain, value: newValue });
    }
  }, [dispatch]);
  const remove = React.useCallback((keyChain, currentValue, index) => {
    if (isArrayValue(currentValue, "formProp.remove")) {
      const newValue = [...currentValue ?? []];
      newValue.splice(index, 1);
      dispatch({ type: "set-path", keyChain, value: newValue });
    }
  }, [dispatch]);
  const insert = React.useCallback((keyChain, currentValue, index, newItem) => {
    if (isArrayValue(currentValue, "formProp.insert")) {
      const newValue = [...currentValue ?? []];
      newValue.splice(index, 0, newItem);
      dispatch({ type: "set-path", keyChain, value: newValue });
    }
  }, [dispatch]);
  const pop = React.useCallback((keyChain, currentValue) => {
    if (isArrayValue(currentValue, "formProp.pop")) {
      const newValue = [...currentValue ?? []];
      newValue.pop();
      dispatch({ type: "set-path", keyChain, value: newValue });
    }
  }, [dispatch]);
  const setTouched = React.useCallback((keyChain, touched) => {
    touchedStateDispatcher({ type: "set-touched", keyChain, touched });
  }, [touchedStateDispatcher]);
  const combinedValidationErrors = React.useMemo(() => [...clientValidationErrors, ...(formConfig == null ? void 0 : formConfig.validationErrors) ?? []], [clientValidationErrors, formConfig == null ? void 0 : formConfig.validationErrors]);
  const bind = React.useCallback((keyChain, bindConfig) => {
    const myTouchedState = touchedStateForKeyChain(touchedState, keyChain);
    const myValidationErrors = validationErrorsByKeyChain(combinedValidationErrors, keyChain);
    return {
      value: valueByKeyChain(formStateLive, keyChain),
      setValue: (newValue) => set(keyChain, newValue),
      bindConfig,
      formConfig,
      myValidationErrors,
      dispatch,
      keyChain,
      fullKeyChain: parentKeyChain ? [...parentKeyChain, ...keyChain] : keyChain,
      initialValue: valueByKeyChain(initialData, keyChain),
      addValidationError: (messages, identifier) => addValidationErrorFromKeyChain(keyChain, messages, identifier),
      clearClientValidationErrors: (...identifiers) => clearValidationErrorsByKeyChain(keyChain, identifiers),
      setTouched: (isTouched) => setTouched(keyChain, isTouched),
      isTouched: !!myTouchedState.length || isGlobalTouched || !!globalTouchOverride,
      myTouchedState,
      clientValidationDispatcher,
      touchedStateDispatcher,
      allTouched: isGlobalTouched,
      validate: (andSetInputToTouched = true, silent = false, validateAll = false) => {
        if (andSetInputToTouched) {
          setTouched(keyChain, true);
        }
        return parseValidationSchema(validateAll ? void 0 : keyChain, silent);
      },
      isValid: !myValidationErrors.length,
      parseValidationSchema
    };
  }, [
    touchedState,
    combinedValidationErrors,
    formStateLive,
    formConfig,
    dispatch,
    parentKeyChain,
    initialData,
    isGlobalTouched,
    globalTouchOverride,
    clientValidationDispatcher,
    touchedStateDispatcher,
    parseValidationSchema,
    set,
    addValidationErrorFromKeyChain,
    clearValidationErrorsByKeyChain,
    setTouched
  ]);
  const validate = React.useCallback((andSetGlobalTouched = true, silent = false) => {
    if (andSetGlobalTouched) {
      setGlobalTouched(true);
    }
    return parseValidationSchema([], silent);
  }, [parseValidationSchema, setGlobalTouched]);
  const formProp = React.useCallback((...keyChain) => {
    const value = valueByKeyChain(formStateRef.current, keyChain);
    const myTouchedState = touchedStateForKeyChain(touchedStateRef.current, keyChain);
    const myValidationErrors = validationErrorsByKeyChain(combinedValidationErrors, keyChain);
    const methods = {
      bind: (bindConfig) => bind(keyChain, bindConfig),
      set: (newValue) => {
        set(keyChain, newValue);
        return formProp(...keyChain);
      },
      clear: () => {
        set(keyChain, void 0);
        return formProp(...keyChain);
      },
      get: () => value,
      add: (newItem) => {
        add(keyChain, value, newItem);
        return formProp(...keyChain);
      },
      pop: () => {
        pop(keyChain, value);
        return formProp(...keyChain);
      },
      insert: (newItem, index) => {
        insert(keyChain, value, index, newItem);
        return formProp(...keyChain);
      },
      remove: (index) => {
        remove(keyChain, value, index);
        return formProp(...keyChain);
      },
      addValidationError: (messages, identifier) => {
        addValidationErrorFromKeyChain(keyChain, messages, identifier);
        return formProp(...keyChain);
      },
      clearClientValidationErrors: (...identifiers) => {
        clearValidationErrorsByKeyChain(keyChain, identifiers);
        return formProp(...keyChain);
      },
      validate: (andSetInputToTouched = true, silent = false) => {
        if (andSetInputToTouched) {
          setTouched(keyChain, true);
        }
        return parseValidationSchema(keyChain, silent);
      },
      isTouched: !!myTouchedState.length || isGlobalTouched || !!globalTouchOverride,
      setTouched: (isTouched) => {
        setTouched(keyChain, isTouched);
        return formProp(...keyChain);
      },
      isValid: !myValidationErrors.length
    };
    return methods;
  }, [
    formStateRef,
    touchedStateRef,
    isGlobalTouched,
    globalTouchOverride,
    combinedValidationErrors,
    bind,
    set,
    add,
    pop,
    insert,
    remove,
    addValidationErrorFromKeyChain,
    clearValidationErrorsByKeyChain,
    parseValidationSchema,
    setTouched
  ]);
  const getFormData = React.useCallback(() => {
    return formStateRef.current;
  }, [formStateRef]);
  const resetFormData = React.useCallback(() => {
    dispatch({ type: "set-all", data: initialData });
  }, [initialData, dispatch]);
  const setFormData = React.useCallback((newFormData) => {
    return dispatch({ type: "set-all", data: newFormData });
  }, [dispatch]);
  const resetTouchedState = React.useCallback(() => {
    setGlobalTouched(false);
    touchedStateDispatcher({ type: "reset-touched" });
  }, [touchedStateDispatcher]);
  return {
    formState: formStateLive,
    formProp,
    resetFormData,
    getFormData,
    setFormData,
    clearClientValidationErrors,
    addValidationError,
    validate,
    touchAll: () => setGlobalTouched(true),
    allTouched: isGlobalTouched,
    isValid: !clientValidationErrors.length && !((_a = formConfig == null ? void 0 : formConfig.validationErrors) == null ? void 0 : _a.length) && parseValidationSchema(void 0, true),
    resetTouchedState
  };
};
export {
  useFormBase
};
//# sourceMappingURL=useFormBase.js.map
