import { akEditorBreakoutPadding, akEditorDefaultLayoutWidth, akEditorFullWidthLayoutWidth, akEditorSwoopCubicBezier, akEditorWideLayoutWidth, breakoutWideScaleRatio } from '@atlaskit/editor-shared-styles';
import { mapBreakpointToLayoutMaxWidth } from '../ui/BaseTheme';
import { getBreakpoint } from '../ui/WidthProvider';
import { parsePx } from './parsePx';

/**
 * Variables required to construct a context for breakout ssr inline script.
 *
 * TODO: Clean this up after: https://product-fabric.atlassian.net/browse/ED-8942
 *
 */

const breakoutConsts = {
  padding: akEditorBreakoutPadding,
  defaultLayoutWidth: akEditorDefaultLayoutWidth,
  wideScaleRatio: breakoutWideScaleRatio,
  fullWidthLayoutWidth: akEditorFullWidthLayoutWidth,
  wideLayoutWidth: akEditorWideLayoutWidth,
  mapBreakpointToLayoutMaxWidth,
  getBreakpoint,
  /**
   * This function can return percentage value or px value depending upon the inputs
   */
  calcBreakoutWidth: breakoutConsts => (layout, containerWidth, padding) => {
    const effectiveFullWidth = containerWidth - (padding !== null && padding !== void 0 ? padding : breakoutConsts.padding);
    switch (layout) {
      case 'full-width':
        return `${Math.min(effectiveFullWidth, breakoutConsts.fullWidthLayoutWidth)}px`;
      case 'wide':
        if (effectiveFullWidth <= 0) {
          return '100%';
        }
        const wideWidth = breakoutConsts.calcWideWidth(breakoutConsts)(containerWidth, undefined, undefined, padding);
        if (wideWidth.endsWith('%')) {
          return `${Math.min(effectiveFullWidth, breakoutConsts.fullWidthLayoutWidth)}px`;
        }
        return wideWidth;
      default:
        return '100%';
    }
  },
  calcBreakoutWithCustomWidth: breakoutConsts => (mode, width, editorContainerWidth) => {
    if (width !== null && width > 0) {
      const effectiveFullWidth = editorContainerWidth - breakoutConsts.padding;
      // if below 0 then expect we're rendering in SSR
      return `${Math.min(width, effectiveFullWidth)}px`;
    }
    return breakoutConsts.calcBreakoutWidth(breakoutConsts)(mode, editorContainerWidth);
  },
  calcLineLength: breakoutConsts => () => breakoutConsts.defaultLayoutWidth,
  calcWideWidth: breakoutConsts => (containerWidth = breakoutConsts.defaultLayoutWidth, maxWidth = Infinity, fallback = '100%', padding) => {
    const effectiveFullWidth = containerWidth - (padding !== null && padding !== void 0 ? padding : breakoutConsts.padding);
    const layoutMaxWidth = breakoutConsts.mapBreakpointToLayoutMaxWidth(breakoutConsts.getBreakpoint(containerWidth));
    const wideWidth = Math.min(Math.ceil(layoutMaxWidth * breakoutConsts.wideScaleRatio), effectiveFullWidth);
    return layoutMaxWidth > wideWidth ? fallback : `${Math.min(maxWidth, wideWidth)}px`;
  }
};
export const absoluteBreakoutWidth = (layout, containerWidth) => {
  const breakoutWidth = breakoutConsts.calcBreakoutWidth(breakoutConsts)(layout, containerWidth);

  // If it's percent, map to max layout size
  if (breakoutWidth.endsWith('%')) {
    switch (layout) {
      case 'full-width':
        return akEditorFullWidthLayoutWidth;
      case 'wide':
        return akEditorWideLayoutWidth;
      default:
        return breakoutConsts.mapBreakpointToLayoutMaxWidth(breakoutConsts.getBreakpoint(containerWidth));
    }
  }
  return parseInt(breakoutWidth, 10);
};
export { breakoutConsts };
export const calcWideWidth = breakoutConsts.calcWideWidth(breakoutConsts);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const calcBreakoutWidth = breakoutConsts.calcBreakoutWidth(breakoutConsts);
export const calcBreakoutWithCustomWidth = breakoutConsts.calcBreakoutWithCustomWidth(breakoutConsts);
export function calculateBreakoutStyles({
  mode,
  widthStateLineLength,
  widthStateWidth
}) {
  const breakoutWidth = calcBreakoutWidth(mode, widthStateWidth);
  const breakoutWidthPx = parsePx(breakoutWidth);
  if (!widthStateLineLength) {
    // lineLength is not normally undefined when this is run for,
    // consumers but can be in SSR, initial render or test (jsdom)
    // environments.
    //
    // this approach doesn't work well with position: fixed, so
    // it breaks things like sticky headers.
    //
    // It can also cause bluriness for some child content (such as iframes)

    return {
      type: 'line-length-unknown',
      width: breakoutWidth,
      minWidth: breakoutWidthPx,
      display: 'flex',
      justifyContent: 'center',
      transform: 'none',
      transition: `min-width 0.5s ${akEditorSwoopCubicBezier}`
    };
  }

  // NOTE
  // At time of writing -- when toggling between full-width and
  // full-page appearance modes. There is a slight delay before
  // the widthState is updated.
  // During this period -- the marginLeftPx will be incorrect.
  // const marginLeftPx = -(breakoutWidthPx - widthStateLineLength) / 2;

  return {
    type: 'line-length-known',
    width: breakoutWidth,
    minWidth: breakoutWidthPx,
    transition: `min-width 0.5s ${akEditorSwoopCubicBezier}`,
    transform: `translateX(-50%)`,
    marginLeft: `50%`
  };
}
export function calcBreakoutWidthPx(mode, widthStateWidth, padding) {
  return parsePx(calcBreakoutWidth(mode, widthStateWidth, padding));
}
// eslint-disable-next-line @atlaskit/editor/no-re-export
export { breakoutResizableNodes } from './breakoutResizableNodes';
// eslint-disable-next-line @atlaskit/editor/no-re-export
export { getBreakoutResizableNodeTypes } from './getBreakoutResizableNodeTypes';
// eslint-disable-next-line @atlaskit/editor/no-re-export
export { getNextBreakoutMode } from './getNextBreakoutMode';
// eslint-disable-next-line @atlaskit/editor/no-re-export
export { getTitle } from './getTitle';