"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.useGridEditing = exports.editingStateInitializer = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _useGridApiMethod = require("../../utils/useGridApiMethod");
var _useGridCellEditing = require("./useGridCellEditing");
var _gridEditRowModel = require("../../../models/gridEditRowModel");
var _useGridRowEditing = require("./useGridRowEditing");
var _gridEditingSelectors = require("./gridEditingSelectors");
var _gridRowsUtils = require("../rows/gridRowsUtils");
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
const editingStateInitializer = state => (0, _extends2.default)({}, state, {
  editRows: {}
});
exports.editingStateInitializer = editingStateInitializer;
const useGridEditing = (apiRef, props) => {
  (0, _useGridCellEditing.useGridCellEditing)(apiRef, props);
  (0, _useGridRowEditing.useGridRowEditing)(apiRef, props);
  const debounceMap = React.useRef({});
  const {
    isCellEditable: isCellEditableProp
  } = props;
  const isCellEditable = React.useCallback(params => {
    if ((0, _gridRowsUtils.isAutoGeneratedRow)(params.rowNode)) {
      return false;
    }
    if (!params.colDef.editable) {
      return false;
    }
    if (!params.colDef.renderEditCell) {
      return false;
    }
    if (isCellEditableProp) {
      return isCellEditableProp(params);
    }
    return true;
  }, [isCellEditableProp]);
  const maybeDebounce = (id, field, debounceMs, callback) => {
    if (!debounceMs) {
      callback();
      return;
    }
    if (!debounceMap.current[id]) {
      debounceMap.current[id] = {};
    }
    if (debounceMap.current[id][field]) {
      const [timeout] = debounceMap.current[id][field];
      clearTimeout(timeout);
    }

    // To run the callback immediately without waiting the timeout
    const runImmediately = () => {
      const [timeout] = debounceMap.current[id][field];
      clearTimeout(timeout);
      callback();
      delete debounceMap.current[id][field];
    };
    const timeout = setTimeout(() => {
      callback();
      delete debounceMap.current[id][field];
    }, debounceMs);
    debounceMap.current[id][field] = [timeout, runImmediately];
  };
  React.useEffect(() => {
    const debounces = debounceMap.current;
    return () => {
      Object.entries(debounces).forEach(([id, fields]) => {
        Object.keys(fields).forEach(field => {
          const [timeout] = debounces[id][field];
          clearTimeout(timeout);
          delete debounces[id][field];
        });
      });
    };
  }, []);
  const runPendingEditCellValueMutation = React.useCallback((id, field) => {
    if (!debounceMap.current[id]) {
      return;
    }
    if (!field) {
      Object.keys(debounceMap.current[id]).forEach(debouncedField => {
        const [, runCallback] = debounceMap.current[id][debouncedField];
        runCallback();
      });
    } else if (debounceMap.current[id][field]) {
      const [, runCallback] = debounceMap.current[id][field];
      runCallback();
    }
  }, []);
  const setEditCellValue = React.useCallback(params => {
    const {
      id,
      field,
      debounceMs
    } = params;
    return new Promise(resolve => {
      maybeDebounce(id, field, debounceMs, async () => {
        const setEditCellValueToCall = props.editMode === _gridEditRowModel.GridEditModes.Row ? apiRef.current.setRowEditingEditCellValue : apiRef.current.setCellEditingEditCellValue;

        // Check if the cell is in edit mode
        // By the time this callback runs the user may have cancelled the editing
        if (apiRef.current.getCellMode(id, field) === _gridEditRowModel.GridCellModes.Edit) {
          const result = await setEditCellValueToCall(params);
          resolve(result);
        }
      });
    });
  }, [apiRef, props.editMode]);
  const getRowWithUpdatedValues = React.useCallback((id, field) => {
    return props.editMode === _gridEditRowModel.GridEditModes.Cell ? apiRef.current.getRowWithUpdatedValuesFromCellEditing(id, field) : apiRef.current.getRowWithUpdatedValuesFromRowEditing(id);
  }, [apiRef, props.editMode]);
  const getEditCellMeta = React.useCallback((id, field) => {
    const editingState = (0, _gridEditingSelectors.gridEditRowsStateSelector)(apiRef.current.state);
    return editingState[id][field];
  }, [apiRef]);
  const editingSharedApi = {
    isCellEditable,
    setEditCellValue,
    getRowWithUpdatedValues,
    unstable_getEditCellMeta: getEditCellMeta
  };
  const editingSharedPrivateApi = {
    runPendingEditCellValueMutation
  };
  (0, _useGridApiMethod.useGridApiMethod)(apiRef, editingSharedApi, 'public');
  (0, _useGridApiMethod.useGridApiMethod)(apiRef, editingSharedPrivateApi, 'private');
};
exports.useGridEditing = useGridEditing;