"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.calcMinWidth = exports.calcMediaSinglePixelWidth = exports.calcMediaSingleMaxWidth = void 0;
exports.calculateOffsetLeft = calculateOffsetLeft;
exports.getMediaSingleInitialWidth = exports.getMaxWidthForNestedNodeNext = exports.getMaxWidthForNestedNode = exports.currentMediaNodeWithPos = void 0;
exports.getMediaSinglePixelWidth = getMediaSinglePixelWidth;
exports.roundToNearest = exports.getParentWidthForNestedMediaSingleNodeForInsertion = exports.getParentWidthForNestedMediaSingleNode = void 0;
var _state = require("@atlaskit/editor-prosemirror/state");
var _editorSharedStyles = require("@atlaskit/editor-shared-styles");
var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
var _richMediaUtils = require("../utils/rich-media-utils");
var _constants = require("./constants");
/**
 * Convert media node width to pixel
 *
 * for legacy experience, image is aligned inside resize handle bar with a gap. So gutterOffset is used to for this use case.
 * for new experience, image is aligned with resize handle bar, so gutterOffset is 0
 *
 * @param width - media single node width
 * @param editorWidth - width of editor
 * @param widthType - width type is defined in the adf document for mediaSingle node, and it is associated with the `width`
 * @param gutterOffset - resize handle bar offset, determines whether align with resize handle bar
 * @returns pixel number for media single node
 */
function getMediaSinglePixelWidth(width, editorWidth) {
  var widthType = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'percentage';
  var gutterOffset = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
  if (widthType === 'pixel') {
    return width;
  }
  return Math.ceil((editorWidth + gutterOffset) * (width / 100) - gutterOffset);
}
/**
 * Convert width attribute to pixel value for legacy (resized or not resisized) and new media single node for new experience
 * @param width node width attribute
 * @param widthType node widthType attribute
 * @param origWidth original media width
 * @param layout node layout attribute
 * @param contentWidth editor content width
 * @param containerWidth editor container width
 * @param gutterOffset gap between resizer handle and media
 * @returns pixel width of the node
 */
var calcMediaSinglePixelWidth = exports.calcMediaSinglePixelWidth = function calcMediaSinglePixelWidth(_ref) {
  var width = _ref.width,
    _ref$widthType = _ref.widthType,
    widthType = _ref$widthType === void 0 ? 'percentage' : _ref$widthType,
    origWidth = _ref.origWidth,
    layout = _ref.layout,
    contentWidth = _ref.contentWidth,
    containerWidth = _ref.containerWidth,
    _ref$gutterOffset = _ref.gutterOffset,
    gutterOffset = _ref$gutterOffset === void 0 ? 0 : _ref$gutterOffset;
  if (widthType === 'pixel' && width) {
    return width;
  }
  switch (layout) {
    case 'wide':
      return calcLegacyWideWidth(containerWidth, origWidth, contentWidth);
    case 'full-width':
      // legacy and new experience have different definitions of full-width,
      // since it's for new experience, we convert to the new definition
      return calcMediaSingleMaxWidth(containerWidth);
    default:
      if (width) {
        return Math.ceil(((contentWidth || containerWidth) + gutterOffset) * (width / 100) - gutterOffset);
      }
  }

  // Handle the case of not resized node with wrapped layout
  // It's possible that the node is first inserted with align layout (e.g. jira)
  // in which the legacy image would render the width as min(origWidth, halfContentWidth).
  // However, new experience won't be able to distinguish the two. Thus, we render halfContentWidth
  // to make sure confluence legacy node is renderered correctly
  if (_constants.wrappedLayouts.includes(layout)) {
    return Math.ceil((contentWidth || containerWidth) / 2);
  }

  // set initial width for not resized legacy image
  return getMediaSingleInitialWidth(origWidth,
  // in case containerWidth is 0, we fallback to undefined to use akEditorDefaultLayoutWidth
  contentWidth || containerWidth || undefined);
};

/**
 * Calculate pixel width for legacy media single
 * @param contentWidth editor content width
 * @param containerWidth editor container width
 */
var calcLegacyWideWidth = function calcLegacyWideWidth(containerWidth, origWidth, contentWidth) {
  if (contentWidth) {
    var wideWidth = Math.ceil(contentWidth * _editorSharedStyles.breakoutWideScaleRatio);
    return wideWidth > containerWidth ? contentWidth : wideWidth;
  }
  return origWidth;
};

/**
 * Calculate maximum width allowed for media single node in fix-width editor in new experience
 * @param containerWidth width of editor container
 */
var calcMediaSingleMaxWidth = exports.calcMediaSingleMaxWidth = function calcMediaSingleMaxWidth(containerWidth, editorAppearance) {
  var fullPagePadding = editorAppearance === 'full-page' && containerWidth <= _editorSharedStyles.akEditorFullPageNarrowBreakout && (0, _experiments.editorExperiment)('platform_editor_preview_panel_responsiveness', true, {
    exposure: true
  }) ? _editorSharedStyles.akEditorGutterPaddingReduced : (0, _editorSharedStyles.akEditorGutterPaddingDynamic)();
  var fullWidthPadding = editorAppearance === 'full-page' ? fullPagePadding * 2 : _editorSharedStyles.akEditorGutterPadding * 2;
  return Math.min(containerWidth - fullWidthPadding, _editorSharedStyles.akEditorFullWidthLayoutWidth);
};

/**
 * Calculate initial media single pixel width.
 * Make it fall between max width and min width
 * @param origWidth original width of image (media node width)
 * @param maxWidth default to akEditorDefaultLayoutWidth (760)
 * @param minWidth default to MEDIA_SINGLE_DEFAULT_MIN_PIXEL_WIDTH (24)
 */
var getMediaSingleInitialWidth = exports.getMediaSingleInitialWidth = function getMediaSingleInitialWidth() {
  var origWidth = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _constants.DEFAULT_IMAGE_WIDTH;
  var maxWidth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _editorSharedStyles.akEditorDefaultLayoutWidth;
  var minWidth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : _constants.MEDIA_SINGLE_DEFAULT_MIN_PIXEL_WIDTH;
  return Math.max(Math.min(origWidth, maxWidth), minWidth);
};
function calculateOffsetLeft(insideInlineLike, insideLayout, pmViewDom, wrapper) {
  var offsetLeft = 0;
  if (wrapper && insideInlineLike && !insideLayout) {
    var currentNode = wrapper;
    var boundingRect = currentNode.getBoundingClientRect();
    offsetLeft = boundingRect.left - pmViewDom.getBoundingClientRect().left;
  }
  return offsetLeft;
}

/**
 * Returns the number rounded to the nearest interval.
 * @param {number} value    The number to round
 * @param {number} interval The numeric interval to round to, default to 0.5
 * @returns {number} the rounded number
 */
var roundToNearest = exports.roundToNearest = function roundToNearest(value) {
  var interval = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _constants.DEFAULT_ROUNDING_INTERVAL;
  return Math.round(value / interval) * interval;
};

/**
 * Retuns minimum value for media single node
 * @param isVideoFile is child media of video type
 * @param contentWidth parent content width
 */
var calcMinWidth = exports.calcMinWidth = function calcMinWidth(isVideoFile, contentWidth) {
  return Math.min(contentWidth, isVideoFile ? _constants.MEDIA_SINGLE_VIDEO_MIN_PIXEL_WIDTH : _constants.MEDIA_SINGLE_DEFAULT_MIN_PIXEL_WIDTH);
};

/**
 * Get parent width for a nested media single node
 * @param view Editor view
 * @param pos node position
 */
var getMaxWidthForNestedNode = exports.getMaxWidthForNestedNode = function getMaxWidthForNestedNode(view, pos) {
  if (typeof pos !== 'number') {
    return null;
  }
  if ((0, _richMediaUtils.isRichMediaInsideOfBlockNode)(view, pos)) {
    var $pos = view.state.doc.resolve(pos);
    var domNode = view.nodeDOM($pos.pos);
    if ($pos.nodeAfter && _richMediaUtils.floatingLayouts.indexOf($pos.nodeAfter.attrs.layout) > -1 && domNode && domNode.parentElement) {
      return domNode.parentElement.offsetWidth;
    }
    if (domNode instanceof HTMLElement) {
      return domNode.offsetWidth;
    }
  }
  return null;
};
var calcParentPadding = function calcParentPadding(view, resolvedPos) {
  // since table has constant padding, use hardcoded constant instead of query the dom
  var tablePadding = 8;
  var _view$state$schema$no = view.state.schema.nodes,
    tableCell = _view$state$schema$no.tableCell,
    tableHeader = _view$state$schema$no.tableHeader;
  return [tableCell, tableHeader].includes(resolvedPos.parent.type) ? tablePadding * 2 : 0;
};

/**
 * Get parent width for a nested media single node for new experience
 * We don't check for mediaSingle selection in this function.
 * @param view Editor view
 * @param pos node position
 * @param forInsertion for insertion
 */
var getMaxWidthForNestedNodeNext = exports.getMaxWidthForNestedNodeNext = function getMaxWidthForNestedNodeNext(view, pos, forInsertion) {
  if (typeof pos !== 'number') {
    return null;
  }
  var $pos = view.state.doc.resolve(pos);
  if ($pos && $pos.parent.type.name !== 'doc') {
    return forInsertion ? getParentWidthForNestedMediaSingleNodeForInsertion($pos, view) : getParentWidthForNestedMediaSingleNode($pos, view);
  }
  return null;
};

/**
 * Get parent content width for nested media single node.
 * @param resolvedPos resolved Position of the node
 * @param view editor view
 * @returns parent content width for nested node
 */
var getParentWidthForNestedMediaSingleNode = exports.getParentWidthForNestedMediaSingleNode = function getParentWidthForNestedMediaSingleNode(resolvedPos, view) {
  var domNode = view.nodeDOM(resolvedPos.pos);
  if (resolvedPos.nodeAfter && _richMediaUtils.floatingLayouts.includes(resolvedPos.nodeAfter.attrs.layout) && domNode && domNode.parentElement) {
    var parentPadding = calcParentPadding(view, resolvedPos);
    return domNode.parentElement.offsetWidth - parentPadding;
  }
  if (domNode instanceof HTMLElement) {
    return domNode.offsetWidth;
  }
  return null;
};

/**
 * Get parent width for nested media single nodes
 * @param resolvedPos resolved Position of the node
 * @param view editor view
 * @returns parent width used for media single initial width on insertion
 */
var getParentWidthForNestedMediaSingleNodeForInsertion = exports.getParentWidthForNestedMediaSingleNodeForInsertion = function getParentWidthForNestedMediaSingleNodeForInsertion(resolvedPos, view) {
  var parentPos = resolvedPos.before(resolvedPos.depth);
  var parentDomNode = view.nodeDOM(parentPos);
  var parentPadding = calcParentPadding(view, resolvedPos);
  if (parentDomNode instanceof HTMLElement) {
    return parentDomNode.offsetWidth - parentPadding;
  }
  return null;
};

/**
 *
 * @param editorState current editor state
 * @returns selected media node (child of mediaSingle only) with position
 */
var currentMediaNodeWithPos = exports.currentMediaNodeWithPos = function currentMediaNodeWithPos(editorState) {
  var doc = editorState.doc,
    selection = editorState.selection,
    schema = editorState.schema;
  if (!doc || !selection || !(selection instanceof _state.NodeSelection) || selection.node.type !== schema.nodes.mediaSingle) {
    return;
  }
  var pos = selection.$anchor.pos + 1;
  var node = doc.nodeAt(pos);
  if (!node || node.type !== schema.nodes.media) {
    return;
  }
  return {
    node: node,
    pos: pos
  };
};