import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
import _toArray from "@babel/runtime/helpers/toArray";
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
import { useState, useCallback, useMemo } from 'react';
import get from 'lodash/get';
import isEqual from 'lodash/isEqual';
import { usePluginStateEffect } from '../usePluginStateEffect';

// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-explicit-any

/**
 * This is designed to iterate through an object to get the path of its result
 * based on separation via "."
 *
 * Example:
 * ```typescript
 * type Test = { deepObject: { value: number } };
 * // Type should be `"deepObject" | "deepObject.value"`
 * type Result = NestedKeys<Test>;
 * ```
 */

/**
 * This is designed to iterate through a path of an object to get the type of its result
 * based on separation via "."
 *
 * Example:
 * ```typescript
 * type Test = { deepObject: { value: number } }
 * // Type should be `number`
 * type Result = Path<Test, 'deepObject.value'>
 * ```
 */

/**
 *
 * NOTE: Generally you want to use `useSharedPluginStateWithSelector` over this which behaves similarly
 * but selects a slice of the state which is more performant.
 *
 * ⚠️⚠️⚠️ This is a debounced hook ⚠️⚠️⚠️
 * If the plugins you are listening to generate multiple shared states while the user is typing,
 * your React Component will get only the last one.
 *
 * Used to return the current plugin state of input dependencies.
 * It will recursively retrieve a slice of the state using a "." to separate
 * parts of the state.
 *
 * Example:
 *
 * ```typescript
 * 	const pluginA: NextEditorPlugin<
		'pluginA',
		{
			sharedState: { deepObj: { value: number | undefined } };
		}
	>
 * ```
 * You can use `const value = useSharedPluginStateSelector(api, 'pluginA.deepObj.value')` to retrieve the value
 *
 * Example in plugin:
 *
 * ```typescript
 * function ExampleContent({ api }: Props) {
 *   const title = useSharedPluginStateSelector(api, 'dog.title')
 *   return <p>{ title } { exampleState.description }</p>
 * }
 *
 * const examplePlugin: NextEditorPlugin<'example', { dependencies: [typeof pluginDog] }> = ({ api }) => {
 *   return {
 *     name: 'example',
 *     contentComponent: () => <ExampleContent api={api} />
 *   }
 * }
 * ```
 *
 * NOTE: If you pass an invalid path, `undefined` will be returned
 *
 * @param api
 * @param plugin
 * @param options
 * @returns
 */
export function useSharedPluginStateSelector(api, plugin) {
  var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  var transformer = useCallback(function (pluginState) {
    var _plugin$split = plugin.split('.'),
      _plugin$split2 = _toArray(_plugin$split),
      pluginName = _plugin$split2[0],
      properties = _arrayLikeToArray(_plugin$split2).slice(1);
    if (!pluginState || (properties === null || properties === void 0 ? void 0 : properties.length) === 0) {
      return undefined;
    }
    return get(pluginState === null || pluginState === void 0 ? void 0 : pluginState["".concat(pluginName, "State")], properties);
  }, [plugin]);
  var pluginNameArray = useMemo(function () {
    var _plugin$split3 = plugin.split('.'),
      _plugin$split4 = _slicedToArray(_plugin$split3, 1),
      pluginName = _plugin$split4[0];
    return [pluginName];
  }, [plugin]);
  var initialState = useMemo(function () {
    var _api$pluginName;
    if (options.disabled) {
      return;
    }
    var _plugin$split5 = plugin.split('.'),
      _plugin$split6 = _slicedToArray(_plugin$split5, 1),
      pluginName = _plugin$split6[0];
    return transformer(_defineProperty({}, "".concat(pluginName, "State"), api === null || api === void 0 || (_api$pluginName = api[pluginName]) === null || _api$pluginName === void 0 ? void 0 : _api$pluginName.sharedState.currentState()));
  }, [plugin, api, options.disabled, transformer]);
  return useSharedPluginStateSelectorInternal(api, pluginNameArray, transformer, initialState, options);
}
function useSharedPluginStateSelectorInternal(api, plugins, transformer, initialState) {
  var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
  var _useState = useState(function () {
      return initialState;
    }),
    _useState2 = _slicedToArray(_useState, 2),
    selectedPluginState = _useState2[0],
    setSelectedPluginState = _useState2[1];
  usePluginStateEffect(api, plugins, function (pluginStates) {
    // `pluginStates`: This is the same type through inference - but typescript doesn't recognise them as they are computed slightly differently
    var transformedValue = transformer(pluginStates);
    if (!isEqual(transformedValue, selectedPluginState)) {
      setSelectedPluginState(function () {
        return transformedValue;
      });
    }
  }, options);
  return selectedPluginState;
}