import React from 'react';
import { getKeys } from './getKeys';
import { serializeValue } from './serializeValue';
export const getKeysAddedRemovedCommon = (object1, object2) => {
  const oldKeys = object1 !== null ? getKeys(object1) : [];
  const newKeys = object2 !== null ? getKeys(object2) : [];
  const removed = oldKeys.filter(key => !newKeys.includes(key));
  const added = newKeys.filter(key => !oldKeys.includes(key));
  const common = oldKeys.filter(key => newKeys.includes(key));
  return {
    added,
    common,
    removed
  };
};
export const getPropsDifference = (object1, object2, curDepth = 0, maxDepth = 2, keysToIgnore = []) => {
  const {
    added,
    common,
    removed
  } = getKeysAddedRemovedCommon(object1, object2);
  const changed = [];
  common.forEach(key => {
    const value1 = object1[key];
    const value2 = object2[key];
    const value1Type = typeof value1;
    const value2Type = typeof value2;

    // Do comparision only if values doesn't match (or reference to same object in memory).
    // Or if key does not exist in keys to ignore.
    if (value1 !== value2 && keysToIgnore.indexOf(key) === -1) {
      // if both key value are objects and not referencing same object in memory.
      //  then get recursive difference.
      if ( /*#__PURE__*/React.isValidElement(value1) || /*#__PURE__*/React.isValidElement(value2)) {
        changed.push({
          key,
          reactElementChanged: true
        });
      } else if (value1Type === 'object' && value2Type === 'object') {
        if (curDepth <= maxDepth) {
          const difference = getPropsDifference(value1, value2, curDepth + 1, maxDepth);
          changed.push({
            key,
            difference
          });
        } else {
          changed.push({
            key,
            maxDepthReached: true
          });
        }
      } else {
        changed.push({
          key,
          oldValue: serializeValue(value1),
          newValue: serializeValue(value2)
        });
      }
    }
  });
  return {
    added,
    changed,
    removed
  };
};
export const getShallowPropsDifference = (object1, object2) => {
  const {
    added,
    common,
    removed
  } = getKeysAddedRemovedCommon(object1, object2);
  const changed = common.filter(key => object1[key] !== object2[key]);
  return {
    added,
    changed,
    removed
  };
};
// eslint-disable-next-line @atlaskit/editor/no-re-export
export { getKeys } from './getKeys';
// eslint-disable-next-line @atlaskit/editor/no-re-export
export { serializeValue } from './serializeValue';