/**
 * @jsxRuntime classic
 * @jsx jsx
 */

import { useCallback, useEffect, useRef, useState } from 'react';
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled, @typescript-eslint/consistent-type-imports -- Ignored via go/DSP-18766; jsx required at runtime for @jsxRuntime classic
import { css, jsx } from '@emotion/react';
import { bind } from 'bind-event-listener';
import { akEditorMenuZIndex } from '@atlaskit/editor-shared-styles';
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
import { withReactEditorViewOuterListeners as withOuterListeners } from '../../ui-react';
import Popup from '../Popup';
import tableSelectorPopup, { TABLE_SELECTOR_BUTTON_GAP, TABLE_SELECTOR_BUTTON_SIZE } from './table-selector';
const TABLE_SELECTOR_PADDING_TOP = 8;
const POPUP_OFFSET = [0, 3];
const TABLE_SELECTOR_PADDING_SIDE = 10;
const DEFAULT_TABLE_SELECTOR_ROWS = 5;
const DEFAULT_TABLE_SELECTOR_COLS = 10;
const DEFAULT_TABLE_SELECTOR_SELECTION_SIZE = 1;
const DEFAULT_MAX_TABLE_SELECTOR_ROWS = 10;
const TableSelectorWithListeners = withOuterListeners(tableSelectorPopup);
const initialSizeState = {
  col: DEFAULT_TABLE_SELECTOR_SELECTION_SIZE,
  row: DEFAULT_TABLE_SELECTOR_SELECTION_SIZE,
  maxCol: DEFAULT_TABLE_SELECTOR_COLS,
  maxRow: DEFAULT_TABLE_SELECTOR_ROWS
};
const tableSelectorPopupWrapperStyles = css({
  borderRadius: "var(--ds-radius-small, 3px)",
  backgroundColor: "var(--ds-surface-overlay, #FFFFFF)",
  boxShadow: "var(--ds-shadow-overlay, 0px 8px 12px #1E1F2126, 0px 0px 1px #1E1F214f)",
  padding: `${"var(--ds-space-100, 8px)"} ${TABLE_SELECTOR_PADDING_SIDE}px`
});
export const TableSelectorPopup = props => {
  const [size, setSize] = useState({
    ...initialSizeState,
    ...props.defaultSize
  });
  const tablePopupRef = useRef(null);
  // If popup opened by keyboard enable keyboard mode
  const isKeyboardMode = useRef(props.isOpenedByKeyboard);
  const enableKeyboardMode = useCallback(() => {
    if (!isKeyboardMode.current) {
      isKeyboardMode.current = true;
    }
  }, [isKeyboardMode]);
  const disableKeyboardMode = useCallback(() => {
    if (isKeyboardMode.current) {
      isKeyboardMode.current = false;
    }
  }, [isKeyboardMode]);

  // Mouse move is used to allow selection changes outside of the popup and is more reactive to changes.
  const handleMouseMove = useCallback(e => {
    if (!tablePopupRef.current) {
      return;
    }
    disableKeyboardMode();
    const tablePopup = tablePopupRef.current;
    const {
      left,
      top
    } = tablePopup.getBoundingClientRect();

    // Mouse position on popup
    const selectedWidth = e.clientX - left;
    const selectedHeight = e.clientY - top;

    // Calculate number grid cells selected
    let selectedGridCols = Math.ceil((selectedWidth - TABLE_SELECTOR_PADDING_SIDE + TABLE_SELECTOR_BUTTON_GAP) / (TABLE_SELECTOR_BUTTON_GAP + TABLE_SELECTOR_BUTTON_SIZE));
    let selectedGridRows = Math.ceil((selectedHeight - TABLE_SELECTOR_PADDING_TOP + TABLE_SELECTOR_BUTTON_GAP) / (TABLE_SELECTOR_BUTTON_GAP + TABLE_SELECTOR_BUTTON_SIZE));
    // Keep the selected rows and columns within the defined bounds
    let gridRows = DEFAULT_TABLE_SELECTOR_ROWS;
    if (selectedGridCols < 1) {
      selectedGridCols = 1;
    }
    if (selectedGridCols > size.maxCol) {
      selectedGridCols = size.maxCol;
    }
    if (selectedGridRows < 1) {
      selectedGridRows = 1;
    }

    // Expand grid when row selection is greater than the default grid size
    if (selectedGridRows >= DEFAULT_TABLE_SELECTOR_ROWS && selectedGridRows < DEFAULT_MAX_TABLE_SELECTOR_ROWS) {
      gridRows = selectedGridRows + 1;
    }
    if (selectedGridRows >= DEFAULT_MAX_TABLE_SELECTOR_ROWS) {
      selectedGridRows = DEFAULT_MAX_TABLE_SELECTOR_ROWS;
      gridRows = DEFAULT_MAX_TABLE_SELECTOR_ROWS;
    }
    if (selectedGridCols !== size.col || selectedGridRows !== size.row) {
      setSize({
        col: selectedGridCols,
        row: selectedGridRows,
        maxCol: DEFAULT_TABLE_SELECTOR_COLS,
        maxRow: gridRows
      });
    }
  }, [disableKeyboardMode, size, setSize]);
  const decreasingSequence = (maxNumber, prevNumber) => {
    let nextNumber = prevNumber - 1;
    if (prevNumber === 1) {
      nextNumber = maxNumber;
    }
    return nextNumber;
  };
  const getMaxRow = (prevSize, eventKey) => {
    switch (eventKey) {
      case 'ArrowDown':
        // Expand the grid size when last row selected
        if (prevSize.maxRow < DEFAULT_MAX_TABLE_SELECTOR_ROWS && prevSize.row >= DEFAULT_TABLE_SELECTOR_ROWS - 1) {
          return prevSize.maxRow + 1;
        }
        if (prevSize.row === DEFAULT_MAX_TABLE_SELECTOR_ROWS) {
          return DEFAULT_TABLE_SELECTOR_ROWS;
        }
        return prevSize.maxRow;
      case 'ArrowLeft':
        const moveToPrevRow = prevSize.col === 1 && prevSize.row > 1;
        const moveToLastRow = prevSize.row === 1 && prevSize.col === 1;
        // Expand the popup to max size when selected row wraps around to last row
        if (moveToLastRow) {
          return DEFAULT_MAX_TABLE_SELECTOR_ROWS;
        }
        // Decrease the popup when decreased row selection
        if (prevSize.maxRow > DEFAULT_TABLE_SELECTOR_ROWS && moveToPrevRow) {
          return prevSize.row;
        }
        return prevSize.maxRow;
      case 'ArrowUp':
        if (prevSize.row === 1) {
          return DEFAULT_MAX_TABLE_SELECTOR_ROWS;
          // Decrease the popup size when decreased row selection
        } else if (prevSize.maxRow > DEFAULT_TABLE_SELECTOR_ROWS) {
          return prevSize.row;
        }
        return prevSize.maxRow;
      case 'ArrowRight':
        const moveToNextRow = prevSize.col === DEFAULT_TABLE_SELECTOR_COLS;
        const increaseMaxRow = prevSize.maxRow < DEFAULT_MAX_TABLE_SELECTOR_ROWS && moveToNextRow && prevSize.row + 1 === prevSize.maxRow;

        // Decrease popup size for wrap around to selection 1 x 1
        if (prevSize.row === DEFAULT_MAX_TABLE_SELECTOR_ROWS && prevSize.col === DEFAULT_TABLE_SELECTOR_COLS) {
          return DEFAULT_TABLE_SELECTOR_ROWS;
          // Decrease the popup size when decreased row selection
        } else if (increaseMaxRow) {
          return prevSize.maxRow + 1;
        }
        return prevSize.maxRow;
      default:
        return prevSize.maxRow;
    }
  };
  const handleInitialButtonFocus = useCallback(() => {
    if (isKeyboardMode.current !== true) {
      enableKeyboardMode();
      setSize(initialSizeState);
    }
  }, [enableKeyboardMode, setSize]);
  const handleKeyDown = useCallback(
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  event => {
    if (event.key === 'ArrowDown') {
      enableKeyboardMode();
      setSize(prevSize => {
        return {
          ...prevSize,
          row: prevSize.row % prevSize.maxRow + 1,
          maxRow: getMaxRow(prevSize, event.key)
        };
      });
      if (editorExperiment('platform_editor_controls', 'variant1')) {
        event.preventDefault();
      }
    }
    if (event.key === 'ArrowRight') {
      enableKeyboardMode();
      setSize(prevSize => {
        const moveToNextRow = prevSize.col === DEFAULT_TABLE_SELECTOR_COLS;
        return {
          ...prevSize,
          col: prevSize.col % DEFAULT_TABLE_SELECTOR_COLS + 1,
          row: moveToNextRow ? prevSize.row % prevSize.maxRow + 1 : prevSize.row,
          maxRow: getMaxRow(prevSize, event.key)
        };
      });
    }
    if (event.key === 'ArrowLeft') {
      enableKeyboardMode();
      setSize(prevSize => {
        const getRow = (prevRow, prevCol) => {
          const row = prevRow;
          // Move to previous row for wrap around
          if (prevSize.col === 1 && prevSize.row > 1) {
            return prevRow - 1;
            // Increase the selection to max size when selected row and column wraps around
          } else if (prevRow === 1 && prevCol === 1) {
            return DEFAULT_MAX_TABLE_SELECTOR_ROWS;
          }
          return row;
        };
        return {
          ...prevSize,
          col: decreasingSequence(prevSize.maxCol, prevSize.col),
          row: getRow(prevSize.row, prevSize.col),
          maxRow: getMaxRow(prevSize, event.key)
        };
      });
    }
    if (event.key === 'ArrowUp') {
      enableKeyboardMode();
      setSize(prevSize => {
        const moveToLastRow = prevSize.row === 1;
        return {
          ...prevSize,
          row: moveToLastRow ? DEFAULT_MAX_TABLE_SELECTOR_ROWS : decreasingSequence(prevSize.maxRow, prevSize.row),
          maxRow: getMaxRow(prevSize, event.key)
        };
      });
      if (editorExperiment('platform_editor_controls', 'variant1')) {
        event.preventDefault();
      }
    }
  }, [enableKeyboardMode, setSize]);
  useEffect(() => {
    let unbind;
    const target = props.allowOutsideSelection ? window : tablePopupRef.current;
    if (target) {
      unbind = bind(target, {
        type: 'mousemove',
        listener: handleMouseMove
      });
    }
    return unbind;
  }, [handleMouseMove, props.allowOutsideSelection, tablePopupRef]);
  const offset = expValEquals('platform_editor_perf_lint_cleanup', 'isEnabled', true) ? POPUP_OFFSET : [0, 3];
  return jsx(Popup, {
    target: props.target,
    offset: offset,
    mountTo: props.popupsMountPoint,
    boundariesElement: props.popupsBoundariesElement,
    scrollableElement: props.popupsScrollableElement,
    focusTrap: true,
    onUnmount: props.onUnmount,
    zIndex: akEditorMenuZIndex
  }, jsx("div", {
    css: tableSelectorPopupWrapperStyles,
    ref: tablePopupRef
  }, jsx(TableSelectorWithListeners, {
    handleClickOutside: props.handleClickOutside,
    handleEscapeKeydown: props.handleEscapeKeydown,
    maxCols: size.maxCol,
    maxRows: size.maxRow,
    onSelection: props.onSelection,
    selectedCol: size.col,
    selectedRow: size.row,
    onKeyDown: handleKeyDown,
    isFocused: isKeyboardMode.current,
    handleInitialButtonFocus: handleInitialButtonFocus
  })));
};

// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
export default TableSelectorPopup;