import { useEvent } from 'rc-util';
import useLayoutEffect from 'rc-util/lib/hooks/useLayoutEffect';
import React from 'react';
import { unstable_batchedUpdates } from 'react-dom';
import runes from 'runes2';
const ELLIPSIS_TEXT = '...';
const measureStyle = {
  visibility: 'hidden',
  whiteSpace: 'inherit',
  lineHeight: 'inherit',
  fontSize: 'inherit'
};
export default function useMeasure(containerRef, content, rows, direction, expanded, expandNode, collapseNode) {
  const contentChars = React.useMemo(() => runes(content), [content]);
  const [maxHeight, setMaxHeight] = React.useState(0);
  const [walkingIndexes, setWalkingIndexes] = React.useState([0, 0]);
  const midIndex = Math.ceil((walkingIndexes[0] + walkingIndexes[1]) / 2);
  const [status, setStatus] = React.useState(100 /* MEASURE_STATUS.STABLE_NO_ELLIPSIS */);
  // ============================ Refs ============================
  const singleRowMeasureRef = React.useRef(null);
  const fullMeasureRef = React.useRef(null);
  const midMeasureRef = React.useRef(null);
  const startMeasure = useEvent(() => {
    // use batch update to avoid async update trigger 2 render
    unstable_batchedUpdates(() => {
      setStatus(1 /* MEASURE_STATUS.PREPARE */);
      setWalkingIndexes([0, direction === 'middle' ? Math.ceil(contentChars.length / 2) : contentChars.length]);
    });
  });
  // Initialize
  useLayoutEffect(() => {
    startMeasure();
  }, [contentChars, rows]);
  // Measure element height
  useLayoutEffect(() => {
    var _a, _b;
    if (status === 1 /* MEASURE_STATUS.PREPARE */) {
      const fullMeasureHeight = ((_a = fullMeasureRef.current) === null || _a === void 0 ? void 0 : _a.offsetHeight) || 0;
      const singleRowMeasureHeight = ((_b = singleRowMeasureRef.current) === null || _b === void 0 ? void 0 : _b.offsetHeight) || 0;
      const rowMeasureHeight = singleRowMeasureHeight * (rows + 0.5);
      if (fullMeasureHeight <= rowMeasureHeight) {
        setStatus(100 /* MEASURE_STATUS.STABLE_NO_ELLIPSIS */);
      } else {
        setMaxHeight(rowMeasureHeight);
        setStatus(2 /* MEASURE_STATUS.MEASURE_WALKING */);
      }
    }
  }, [status]);
  // Walking measure
  useLayoutEffect(() => {
    var _a;
    if (status === 2 /* MEASURE_STATUS.MEASURE_WALKING */) {
      const diff = walkingIndexes[1] - walkingIndexes[0];
      const midHeight = ((_a = midMeasureRef.current) === null || _a === void 0 ? void 0 : _a.offsetHeight) || 0;
      if (diff > 1) {
        if (midHeight > maxHeight) {
          setWalkingIndexes([walkingIndexes[0], midIndex]);
        } else {
          setWalkingIndexes([midIndex, walkingIndexes[1]]);
        }
      } else {
        if (midHeight > maxHeight) {
          setWalkingIndexes([walkingIndexes[0], walkingIndexes[0]]);
        } else {
          setWalkingIndexes([walkingIndexes[1], walkingIndexes[1]]);
        }
        setStatus(99 /* MEASURE_STATUS.STABLE_ELLIPSIS */);
      }
    }
  }, [status, walkingIndexes]);
  // =========================== Render ===========================
  /** Render by cut index */
  const renderContent = index => {
    const prefixContent = contentChars.slice(0, index);
    const suffixContent = contentChars.slice(contentChars.length - index);
    return React.createElement(React.Fragment, null, direction === 'start' && React.createElement(React.Fragment, null, expandNode, ELLIPSIS_TEXT), direction !== 'start' && prefixContent.join(''), direction === 'middle' && React.createElement(React.Fragment, null, ELLIPSIS_TEXT, expandNode, ELLIPSIS_TEXT), direction !== 'end' && suffixContent.join(''), direction === 'end' && React.createElement(React.Fragment, null, ELLIPSIS_TEXT, expandNode));
  };
  const finalContent = React.useMemo(() => {
    if (expanded || status === 100 /* MEASURE_STATUS.STABLE_NO_ELLIPSIS */) {
      return React.createElement(React.Fragment, {
        key: 'display'
      }, content, status === 99 /* MEASURE_STATUS.STABLE_ELLIPSIS */ && collapseNode);
    }
    if (status === 99 /* MEASURE_STATUS.STABLE_ELLIPSIS */) {
      return renderContent(midIndex);
    }
    return null;
  }, [expanded, status, content, collapseNode, midIndex]);
  const allNodes = React.createElement(React.Fragment, null, status === 1 /* MEASURE_STATUS.PREPARE */ && React.createElement("div", {
    key: 'full',
    "aria-hidden": true,
    ref: fullMeasureRef,
    style: measureStyle
  }, content, expandNode), status === 1 /* MEASURE_STATUS.PREPARE */ && React.createElement("div", {
    key: 'stable',
    "aria-hidden": true,
    ref: singleRowMeasureRef,
    style: measureStyle
  }, '\u00A0'), status === 2 /* MEASURE_STATUS.MEASURE_WALKING */ && React.createElement("div", {
    key: 'walking-mid',
    "aria-hidden": true,
    ref: midMeasureRef,
    style: measureStyle
  }, renderContent(midIndex)), finalContent);
  return [allNodes, startMeasure];
}