import { DEFAULT_DEBOUNCE_DELAY } from 'core/constants/debounce';
import { useEffect, useState } from 'react';
import { useDebouncedCallback } from 'use-debounce';
import { useStores } from '../useStores';

export const useComputedValue = ({ computedValueName }) => {
  const { calculationStore } = useStores();
  return {
    value: calculationStore[computedValueName](),
  };
};

export const useStoreValue = ({ valueName }) => {
  const { calculationStore } = useStores();
  const [currentValue, setCurrentValue] = useState(undefined);

  const sourceValue = calculationStore.values[valueName];

  // get value from store
  useEffect(() => {
    setCurrentValue(sourceValue);
  }, [sourceValue]);

  // set value to store
  const debounced = useDebouncedCallback(
    (valueName, value) => calculationStore.setValue(valueName, value),
    DEFAULT_DEBOUNCE_DELAY,
  );
  useEffect(() => {
    debounced(valueName, currentValue);
  }, [currentValue]);

  return { value: currentValue, setCurrentValue };
};

export const useTableValue = ({
  tableName,
  rowIndex,
  propName,
  columnCallback,
}) => {
  const { calculationStore } = useStores();
  const { calculationProcess } = calculationStore.stores;
  const [currentValue, setCurrentValue] = useState(undefined);

  //get row value from store
  const targetTable = calculationStore?.tables?.[tableName];
  const sourceValue = targetTable?.rows?.[rowIndex]?.[propName]?.value;
  useEffect(() => {
    if (sourceValue !== undefined) {
      setCurrentValue(sourceValue);
    }
  }, [sourceValue]);

  const debouncedSetTableRow = useDebouncedCallback(
    (tableName, rowIndex, rows) => {
      calculationStore.setTableRow(tableName, rowIndex)(rows);
    },
    DEFAULT_DEBOUNCE_DELAY,
  );

  //set row value to store
  useEffect(() => {
    if (currentValue !== undefined)
      debouncedSetTableRow(tableName, rowIndex, {
        [propName]: {
          value: currentValue,
        },
      });
  }, [currentValue]);

  //use cell callback (only during default process)
  const debouncedCellCallback = useDebouncedCallback(
    (
      callback,
      calculationStore,
      calculationProcess,
      tableName,
      rowIndex,
      value,
    ) => {
      callback({
        calculationStore,
        calculationProcess,
        tableName,
        rowIndex,
        value,
      });
    },
    DEFAULT_DEBOUNCE_DELAY,
  );

  useEffect(() => {
    if (columnCallback && calculationProcess.noProcesses())
      debouncedCellCallback(
        columnCallback,
        calculationStore,
        calculationProcess,
        tableName,
        rowIndex,
        currentValue,
      );
  }, [currentValue]);

  return { value: currentValue, setCurrentValue };
};
