import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
import { bind, bindAll } from 'bind-event-listener';
import { akEditorDefaultLayoutWidth, akEditorFullWidthLayoutWidth, akEditorGutterPadding, akEditorGutterPaddingDynamic, akEditorGutterPaddingReduced, akEditorFullPageNarrowBreakout } from '@atlaskit/editor-shared-styles';
import { fg } from '@atlaskit/platform-feature-flags';
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
import { ACTION, ACTION_SUBJECT, EVENT_TYPE } from '../analytics';
import { LAYOUT_COLUMN_PADDING, LAYOUT_SECTION_MARGIN } from '../styles';
import { getBrowserInfo } from '../utils/browser';
import Resizer from './Resizer';
import { ResizerBreakoutModeLabel } from './ResizerBreakoutModeLabel';
import { SNAP_GAP, useBreakoutGuidelines } from './useBreakoutGuidelines';
var breakoutSupportedNodes = ['layoutSection', 'expand', 'codeBlock'];
var getHandleStyle = function getHandleStyle(node, hidden) {
  var layoutMarginOffset = 12;
  if (hidden) {
    return {
      left: {
        display: 'none'
      },
      right: {
        display: 'none'
      }
    };
  }
  switch (node) {
    case 'codeBlock':
      return {
        left: {
          left: '-12px'
        },
        right: {
          right: '-12px'
        }
      };
    // expand and layout section elements have a negative margin applied
    default:
      var handleOffset = fg('platform_editor_nested_dnd_styles_changes') ? LAYOUT_SECTION_MARGIN * 2 + layoutMarginOffset : LAYOUT_COLUMN_PADDING * 2;
      return {
        left: {
          left: "-".concat(handleOffset, "px"),
          height: 'calc(100% - 8px)',
          bottom: '0px',
          top: 'unset'
        },
        right: {
          right: "-".concat(handleOffset, "px"),
          height: 'calc(100% - 8px)',
          bottom: '0px',
          top: 'unset'
        }
      };
  }
};
export var ignoreResizerMutations = function ignoreResizerMutations(mutation) {
  if (mutation.target instanceof Element) {
    return mutation.target.classList.contains('resizer-item') || mutation.type === 'attributes' && mutation.attributeName === 'style';
  }
  return mutation.type === 'attributes' && mutation.attributeName === 'style';
};
var resizingStyles = {
  left: '50%',
  transform: 'translateX(-50%)',
  display: 'grid'
};

// Apply grid to stop drag handles rendering inside .resizer-item affecting its height
var defaultStyles = {
  display: 'grid'
};
var RESIZE_STEP_VALUE = 10;
var RESIZER_ENABLE_HANDLES = {
  left: true,
  right: true
};
/**
 * BreakoutResizer is a common component used to resize nodes that support the 'Breakout' mark, so it requires
 * correct ADF support.
 *
 * use experiment platform_editor_advanced_layouts
 * @param root0
 * @param root0.editorView
 * @param root0.nodeType
 * @param root0.getPos
 * @param root0.getRef
 * @param root0.disabled
 * @param root0.getEditorWidth
 * @param root0.parentRef
 * @param root0.displayGuidelines
 * @param root0.editorAnalyticsApi
 * @param root0.displayGapCursor
 * @param root0.onResizeStart
 * @param root0.dynamicFullWidthGuidelineOffset
 * @param root0.hidden Hide the resizer handles without outright unrendering them
 * @returns BreakoutResizer component
 * @example
 */
var BreakoutResizer = function BreakoutResizer(_ref) {
  var editorView = _ref.editorView,
    nodeType = _ref.nodeType,
    getPos = _ref.getPos,
    getRef = _ref.getRef,
    disabled = _ref.disabled,
    getEditorWidth = _ref.getEditorWidth,
    parentRef = _ref.parentRef,
    displayGuidelines = _ref.displayGuidelines,
    editorAnalyticsApi = _ref.editorAnalyticsApi,
    displayGapCursor = _ref.displayGapCursor,
    onResizeStart = _ref.onResizeStart,
    dynamicFullWidthGuidelineOffset = _ref.dynamicFullWidthGuidelineOffset,
    _ref$hidden = _ref.hidden,
    hidden = _ref$hidden === void 0 ? false : _ref$hidden;
  var _useState = useState({
      minWidth: undefined,
      maxWidth: undefined,
      isResizing: false
    }),
    _useState2 = _slicedToArray(_useState, 2),
    _useState2$ = _useState2[0],
    minWidth = _useState2$.minWidth,
    maxWidth = _useState2$.maxWidth,
    isResizing = _useState2$.isResizing,
    setResizingState = _useState2[1];
  var areResizeMetaKeysPressed = useRef(false);
  var resizerRef = useRef(null);
  var _useBreakoutGuideline = useBreakoutGuidelines(getEditorWidth, isResizing && editorExperiment('single_column_layouts', true), dynamicFullWidthGuidelineOffset),
    snaps = _useBreakoutGuideline.snaps,
    currentLayout = _useBreakoutGuideline.currentLayout,
    guidelines = _useBreakoutGuideline.guidelines,
    setCurrentWidth = _useBreakoutGuideline.setCurrentWidth;
  var browser = getBrowserInfo();
  useEffect(function () {
    if (displayGuidelines) {
      displayGuidelines(guidelines || []);
    }
  }, [displayGuidelines, guidelines]);

  // Relying on re-renders caused by selection changes inside/around node
  var isSelectionInNode = useMemo(function () {
    var pos = getPos();
    if (pos === undefined) {
      return false;
    }
    var node = editorView.state.doc.nodeAt(pos);
    if (node === null) {
      return false;
    }
    var endPos = pos + node.nodeSize;
    var startPos = pos;
    var _editorView$state$sel = editorView.state.selection,
      $from = _editorView$state$sel.$from,
      $to = _editorView$state$sel.$to;
    return $from.pos >= startPos && endPos >= $to.pos;
  }, [editorView.state.doc, editorView.state.selection, getPos]);
  var handleResizeStart = useCallback(function () {
    onResizeStart === null || onResizeStart === void 0 || onResizeStart();
    var newMinWidth;
    var newMaxWidth;
    var widthState = getEditorWidth();
    var dispatch = editorView.dispatch,
      state = editorView.state;
    displayGapCursor(false);
    if (widthState !== undefined && widthState.lineLength !== undefined && widthState.width !== undefined) {
      var padding = widthState.width <= akEditorFullPageNarrowBreakout && editorExperiment('platform_editor_preview_panel_responsiveness', true, {
        exposure: true
      }) ? akEditorGutterPaddingReduced : akEditorGutterPaddingDynamic();
      newMaxWidth = Math.min(widthState.width - padding * 2 - akEditorGutterPadding, akEditorFullWidthLayoutWidth);
      newMinWidth = Math.min(widthState.lineLength, akEditorDefaultLayoutWidth, newMaxWidth);
    }
    setResizingState({
      isResizing: true,
      minWidth: newMinWidth,
      maxWidth: newMaxWidth
    });
    dispatch(state.tr.setMeta('is-resizer-resizing', true));
  }, [onResizeStart, getEditorWidth, editorView, displayGapCursor]);
  var handleResize = useCallback(function (originalState, delta) {
    if (editorExperiment('single_column_layouts', true)) {
      var newWidth = originalState.width + delta.width;
      setCurrentWidth(newWidth);
    }
  }, [setCurrentWidth]);
  var handleResizeStop = useCallback(function (originalState, delta) {
    var newWidth = originalState.width + delta.width;
    var pos = getPos();
    if (pos === undefined) {
      return;
    }
    var state = editorView.state,
      dispatch = editorView.dispatch;
    var breakout = state.schema.marks.breakout;
    var node = state.doc.nodeAt(pos);
    var newTr = state.tr;
    if (node && breakoutSupportedNodes.includes(node.type.name)) {
      if (currentLayout && ['wide', 'full-width'].includes(currentLayout) && editorExperiment('single_column_layouts', true)) {
        newTr.setNodeMarkup(pos, node.type, node.attrs, [breakout.create({
          mode: currentLayout,
          width: null
        })]);
      } else {
        var newBreakoutWidth = Math.max(newWidth, akEditorDefaultLayoutWidth);
        newTr.setNodeMarkup(pos, node.type, node.attrs, [breakout.create({
          width: newBreakoutWidth
        })]);
        var breakoutResizePayload = {
          action: ACTION.RESIZED,
          actionSubject: ACTION_SUBJECT.ELEMENT,
          eventType: EVENT_TYPE.TRACK,
          attributes: {
            nodeType: node.type.name,
            prevWidth: originalState.width,
            newWidth: newBreakoutWidth
          }
        };
        editorAnalyticsApi === null || editorAnalyticsApi === void 0 || editorAnalyticsApi.attachAnalyticsEvent(breakoutResizePayload)(newTr);
      }
    }
    newTr.setMeta('is-resizer-resizing', false).setMeta('scrollIntoView', false);
    displayGapCursor(true);
    dispatch(newTr);
    setResizingState({
      isResizing: false,
      minWidth: undefined,
      maxWidth: undefined
    });
    setCurrentWidth(null);
  }, [getPos, editorView, displayGapCursor, setCurrentWidth, currentLayout, editorAnalyticsApi]);
  var handleEscape = useCallback(function () {
    editorView === null || editorView === void 0 || editorView.focus();
  }, [editorView]);
  var handleLayoutSizeChangeOnKeypress = useCallback(function (step) {
    if (!parentRef) {
      return;
    }
    var resizerItem = parentRef.closest('.resizer-item');
    if (!(resizerItem instanceof HTMLElement)) {
      return;
    }
    var newWidth = resizerItem.offsetWidth + step;
    if (maxWidth && newWidth > maxWidth || minWidth && newWidth < minWidth) {
      return;
    }
    handleResizeStop({
      width: resizerItem.offsetWidth,
      x: 0,
      y: 0,
      height: 0
    }, {
      width: step,
      height: 0
    });
  }, [handleResizeStop, maxWidth, minWidth, parentRef]);
  var resizeHandleKeyDownHandler = useCallback(function (event) {
    var isBracketKey = event.code === 'BracketRight' || event.code === 'BracketLeft';
    var metaKey = browser.mac ? event.metaKey : event.ctrlKey;
    if (event.altKey || metaKey || event.shiftKey) {
      areResizeMetaKeysPressed.current = true;
    }
    if (event.altKey && metaKey) {
      if (isBracketKey) {
        event.preventDefault();
        handleLayoutSizeChangeOnKeypress(event.code === 'BracketRight' ? RESIZE_STEP_VALUE : -RESIZE_STEP_VALUE);
      }
    } else if (!areResizeMetaKeysPressed.current) {
      handleEscape();
    }
  }, [handleEscape, handleLayoutSizeChangeOnKeypress, browser]);
  var resizeHandleKeyUpHandler = useCallback(function (event) {
    if (event.altKey || event.metaKey) {
      areResizeMetaKeysPressed.current = false;
    }
    return;
  }, [areResizeMetaKeysPressed]);
  var resizerGlobalKeyDownHandler = useCallback(function (event) {
    if (!resizerRef.current) {
      return;
    }
    var resizeHandleThumbEl = resizerRef.current.getResizerThumbEl();
    var metaKey = browser.mac ? event.metaKey : event.ctrlKey;
    var isTargetResizeHandle = event.target instanceof HTMLElement && event.target.classList.contains('resizer-handle-thumb');
    if (event.altKey && event.shiftKey && metaKey && event.code === 'KeyR' || isTargetResizeHandle && (event.altKey || metaKey || event.shiftKey)) {
      event.preventDefault();
      if (!resizeHandleThumbEl) {
        return;
      }
      resizeHandleThumbEl.focus();
      resizeHandleThumbEl.scrollIntoView({
        behavior: 'smooth',
        block: 'center',
        inline: 'nearest'
      });
    }
  }, [resizerRef, browser]);
  useLayoutEffect(function () {
    if (!resizerRef.current || !editorView) {
      return;
    }
    var resizeHandleThumbEl = resizerRef.current.getResizerThumbEl();
    if (!resizeHandleThumbEl) {
      return;
    }
    var editorViewDom = editorView.dom;
    var unbindEditorViewDom = bind(editorViewDom, {
      type: 'keydown',
      listener: resizerGlobalKeyDownHandler
    });
    var unbindResizeHandle = bindAll(resizeHandleThumbEl, [{
      type: 'keydown',
      listener: resizeHandleKeyDownHandler
    }, {
      type: 'keyup',
      listener: resizeHandleKeyUpHandler
    }]);
    return function () {
      unbindEditorViewDom();
      unbindResizeHandle();
    };
  }, [editorView, resizerGlobalKeyDownHandler, resizeHandleKeyDownHandler, resizeHandleKeyUpHandler]);
  if (disabled) {
    return /*#__PURE__*/React.createElement("div", {
      "data-testid": "breakout-resizer-editor-view-wrapper",
      ref: function ref(_ref2) {
        return getRef && getRef(_ref2);
      }
    });
  }
  return /*#__PURE__*/React.createElement(Resizer, {
    ref: resizerRef,
    enable: expValEquals('platform_editor_perf_lint_cleanup', 'isEnabled', true) ? RESIZER_ENABLE_HANDLES : {
      left: true,
      right: true
    },
    snap: snaps || undefined,
    snapGap: SNAP_GAP,
    handleStyles: getHandleStyle(nodeType, hidden),
    minWidth: minWidth,
    maxWidth: maxWidth
    // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop
    ,
    style: isResizing ? resizingStyles : defaultStyles,
    handleResizeStart: handleResizeStart,
    handleResizeStop: handleResizeStop,
    handleResize: handleResize,
    childrenDOMRef: getRef,
    resizeRatio: 2,
    isHandleVisible: isSelectionInNode,
    handleSize: "clamped",
    handleHighlight: "full-height",
    handlePositioning: "adjacent",
    handleAlignmentMethod: "sticky",
    labelComponent: currentLayout && editorExperiment('single_column_layouts', true) && ['full-width', 'wide'].includes(currentLayout || '') && /*#__PURE__*/React.createElement(ResizerBreakoutModeLabel, {
      layout: currentLayout
    })
  });
};
export { BreakoutResizer };