/**
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */
'use strict';

var LexicalComposerContext = require('@lexical/react/LexicalComposerContext');
var table = require('@lexical/table');
var lexical = require('lexical');
var react = require('react');

/**
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 */
function TablePlugin() {
  const [editor] = LexicalComposerContext.useLexicalComposerContext();
  react.useEffect(() => {
    if (!editor.hasNodes([table.TableNode, table.TableCellNode, table.TableRowNode])) {
      {
        throw Error(`TablePlugin: TableNode, TableCellNode or TableRowNode not registered on editor`);
      }
    }

    return editor.registerCommand(table.INSERT_TABLE_COMMAND, ({
      columns,
      rows,
      includeHeaders
    }) => {
      const selection = lexical.$getSelection();

      if (!lexical.$isRangeSelection(selection)) {
        return true;
      }

      const focus = selection.focus;
      const focusNode = focus.getNode();

      if (focusNode !== null) {
        const tableNode = table.$createTableNodeWithDimensions(Number(rows), Number(columns), includeHeaders);

        if (lexical.$isRootOrShadowRoot(focusNode)) {
          const target = focusNode.getChildAtIndex(focus.offset);

          if (target !== null) {
            target.insertBefore(tableNode);
          } else {
            focusNode.append(tableNode);
          }

          tableNode.insertBefore(lexical.$createParagraphNode());
        } else {
          const topLevelNode = focusNode.getTopLevelElementOrThrow();
          topLevelNode.insertAfter(tableNode);
        }

        tableNode.insertAfter(lexical.$createParagraphNode());
        const firstCell = tableNode.getFirstChildOrThrow().getFirstChildOrThrow();
        firstCell.select();
      }

      return true;
    }, lexical.COMMAND_PRIORITY_EDITOR);
  }, [editor]);
  react.useEffect(() => {
    const tableSelections = new Map();

    const initializeTableNode = tableNode => {
      const nodeKey = tableNode.getKey();
      const tableElement = editor.getElementByKey(nodeKey);

      if (tableElement && !tableSelections.has(nodeKey)) {
        const tableSelection = table.applyTableHandlers(tableNode, tableElement, editor);
        tableSelections.set(nodeKey, tableSelection);
      }
    }; // Plugins might be loaded _after_ initial content is set, hence existing table nodes
    // won't be initialized from mutation[create] listener. Instead doing it here,


    editor.getEditorState().read(() => {
      const tableNodes = lexical.$nodesOfType(table.TableNode);

      for (const tableNode of tableNodes) {
        if (table.$isTableNode(tableNode)) {
          initializeTableNode(tableNode);
        }
      }
    });
    const unregisterMutationListener = editor.registerMutationListener(table.TableNode, nodeMutations => {
      for (const [nodeKey, mutation] of nodeMutations) {
        if (mutation === 'created') {
          editor.getEditorState().read(() => {
            const tableNode = lexical.$getNodeByKey(nodeKey);

            if (table.$isTableNode(tableNode)) {
              initializeTableNode(tableNode);
            }
          });
        } else if (mutation === 'destroyed') {
          const tableSelection = tableSelections.get(nodeKey);

          if (tableSelection !== undefined) {
            tableSelection.removeListeners();
            tableSelections.delete(nodeKey);
          }
        }
      }
    });
    return () => {
      unregisterMutationListener(); // Hook might be called multiple times so cleaning up tables listeners as well,
      // as it'll be reinitialized during recurring call

      for (const [, tableSelection] of tableSelections) {
        tableSelection.removeListeners();
      }
    };
  }, [editor]);
  return null;
}

exports.TablePlugin = TablePlugin;
