import { useCallback, useMemo, useState } from 'react';
import { akEditorCalculatedWideLayoutWidth, akEditorDefaultLayoutWidth, akEditorFullWidthLayoutWidth, akEditorGutterPadding, akEditorGutterPaddingDynamic, akEditorGutterPaddingReduced, akEditorFullPageNarrowBreakout, breakoutWideScaleRatio } from '@atlaskit/editor-shared-styles';
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
export const SNAP_GAP = 8;
const GUIDELINE_KEYS = {
  lineLength: 'grid',
  wide: 'wide',
  fullWidth: 'full_width'
};
const CURRENT_LAYOUT_KEYS = {
  lineLength: 'center',
  wide: 'wide',
  fullWidth: 'full-width'
};
const roundToNearest = (value, interval = 0.5) => Math.round(value / interval) * interval;

// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
export function useBreakoutGuidelines(getEditorWidth, isResizing, dynamicFullWidthGuidelineOffset = 0) {
  const widthState = getEditorWidth();
  const {
    lineLength,
    wide,
    fullWidth
  } = useMemo(() => {
    if (!isResizing) {
      return {};
    }
    const {
      width,
      lineLength
    } = widthState || {};
    const wideCalWithRatio = lineLength ? Math.round(lineLength * breakoutWideScaleRatio) : undefined;
    // When page is full width, lineLength from widthState can be much wider than 760.
    // But the lineLength variable here is being used like a const 760.
    // when the page is full width, the calculation of wide is wrong.
    // Actuall the wide is the wide breakout point, which is
    const wide = editorExperiment('single_column_layouts', true) ? akEditorCalculatedWideLayoutWidth : wideCalWithRatio;
    const padding = width && width <= akEditorFullPageNarrowBreakout && editorExperiment('platform_editor_preview_panel_responsiveness', true, {
      exposure: true
    }) ? akEditorGutterPaddingReduced : akEditorGutterPaddingDynamic();
    const layoutCalculatedWidth = width ? width - (padding + dynamicFullWidthGuidelineOffset) * 2 : undefined;
    const fullWidth = width && layoutCalculatedWidth ? Math.min(layoutCalculatedWidth, akEditorFullWidthLayoutWidth) : undefined;
    return {
      wide,
      fullWidth,
      // When page is full width, lineLength from widthState can be much wider than 760.
      // But the lineLength variable here is being used like a const 760.
      lineLength: editorExperiment('single_column_layouts', true) ? akEditorDefaultLayoutWidth : lineLength
    };
  }, [widthState, isResizing, dynamicFullWidthGuidelineOffset]);

  // calculate snapping width
  const defaultSnappingWidths = useMemo(() => {
    if (!fullWidth || !wide || !lineLength || fullWidth <= (editorExperiment('single_column_layouts', true) ? akEditorDefaultLayoutWidth : lineLength)) {
      return null;
    }
    if (fullWidth - wide > SNAP_GAP) {
      return {
        lineLength,
        wide,
        fullWidth
      };
    }
    if (fullWidth <= wide && fullWidth - lineLength > SNAP_GAP) {
      return {
        lineLength,
        fullWidth
      };
    }
    return null;
  }, [fullWidth, lineLength, wide]);
  const snaps = useMemo(() => {
    if (!isResizing || !defaultSnappingWidths) {
      return null;
    }
    return {
      x: Object.values(defaultSnappingWidths)
    };
  }, [defaultSnappingWidths, isResizing]);

  // calculate guidelines, and calculate which lines are active
  const [currentLayout, setCurrentLayout] = useState(null);
  const guidelines = useMemo(() => {
    const guidelines = [];
    if (!defaultSnappingWidths) {
      return guidelines;
    }
    Object.entries(defaultSnappingWidths).map(([key, value]) => {
      if (value) {
        guidelines.push({
          key: `${GUIDELINE_KEYS[key]}_left`,
          position: {
            x: -roundToNearest(value / 2)
          },
          active: currentLayout === CURRENT_LAYOUT_KEYS[key]
        });
        guidelines.push({
          key: `${GUIDELINE_KEYS[key]}_right`,
          position: {
            x: roundToNearest(value / 2)
          },
          active: currentLayout === CURRENT_LAYOUT_KEYS[key]
        });
      }
    });
    return guidelines;
  }, [defaultSnappingWidths, currentLayout]);
  const setCurrentWidth = useCallback(newWidth => {
    if (typeof newWidth !== 'number') {
      setCurrentLayout(null);
      return;
    }
    if (lineLength && Math.abs(newWidth - lineLength) < SNAP_GAP / 2) {
      setCurrentLayout('center');
    } else if (wide && Math.abs(newWidth - wide) < SNAP_GAP / 2) {
      setCurrentLayout('wide');
    } else if (fullWidth && (
    // we only allow snap from one side, so we don't use Math.abs here
    fullWidth + akEditorGutterPadding - newWidth < SNAP_GAP / 2 || newWidth >= fullWidth)) {
      setCurrentLayout('full-width');
    } else {
      setCurrentLayout(null);
    }
  }, [lineLength, wide, fullWidth]);
  return {
    snaps,
    currentLayout,
    guidelines,
    setCurrentWidth
  };
}