import {
  ReactNode,
  createContext,
  useCallback,
  useContext,
  useMemo,
} from 'react';

import { UseFormidableReturn } from './FormidableConfig';

export type FromContextProps = {
  form: UseFormidableReturn;
};

export const formContext = createContext<FromContextProps>({
  form: {
    getDeltaData: ({}: { omit?: string[]; only?: string[] }) => {
      return {};
    },
    isFormModified: false,
    isModify: {},
    restoreValues: () => {},
    restoreValue: (_data: object) => {},
    setValues: (_data: object) => {},
    values: {},
    errors: {},
    configuration: {
      enableReset: false,
      enableModifyNotification: false,
      singleLineForm: false,
    },
    deltaConfig: {},
  },
});

export const useFormidableContext = () => {
  const context = useContext(formContext);
  if (!context) {
    throw new Error('useFormContext must be used within a FormProvider');
  }
  if (!context.form) {
    throw new Error('useFormContext without defining a From');
  }
  return context;
};
export const useFormidableContextElement = (name: string) => {
  const { form } = useFormidableContext();
  if (name === undefined) {
    console.error(
      "Can not request useFormidableContextElement with empty 'name'"
    );
  }
  const onChange = useCallback(
    (value) => {
      console.log(`new values: ${name}=>${value}`);
      form.setValues({ [name]: value });
    },
    [name, form, form.setValues]
  );
  const onRestore = useCallback(() => {
    console.log('Restore value : ' + name);
    form.restoreValue({ [name]: true });
  }, [name, form, form.restoreValue]);
  return {
    form,
    value: form.values[name] || '',
    error: form.errors[name],
    isModify: form.isModify[name],
    onChange,
    onRestore,
  };
};

export type FormidableContextProps = {
  form: UseFormidableReturn;
  children: ReactNode;
};

export const FormidableContext = ({
  form,
  children,
}: FormidableContextProps) => {
  const memoContext = useMemo(
    () => ({
      form,
    }),
    [form]
  );
  return (
    <formContext.Provider value={memoContext}>{children}</formContext.Provider>
  );
};
