import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
import { findWrapping } from '@atlaskit/editor-prosemirror/transform';
import { safeInsert } from '@atlaskit/editor-prosemirror/utils';
import { removeBlockMarks } from './editor-core-utils';

/**
 * This function creates a new transaction that wraps the current selection
 * in the specified node type if it results in a valid transaction.
 * If not valid, it performs a safe insert operation.
 *
 * Example of when wrapping might not be valid is when attempting to wrap
 * content that is already inside a panel with another panel
 */
export function createWrapSelectionTransaction(_ref) {
  var state = _ref.state,
    type = _ref.type,
    nodeAttributes = _ref.nodeAttributes;
  var tr = state.tr;
  var _state$schema$marks = state.schema.marks,
    alignment = _state$schema$marks.alignment,
    indentation = _state$schema$marks.indentation;

  /** Alignment or Indentation is not valid inside block types */
  var removeAlignTr = removeBlockMarks(state, [alignment, indentation]);
  tr = removeAlignTr || tr;

  /**Get range and wrapping needed for the selection*/
  var _getWrappingOptions = getWrappingOptions(state, type, nodeAttributes),
    range = _getWrappingOptions.range,
    wrapping = _getWrappingOptions.wrapping;
  if (wrapping) {
    tr.wrap(range, wrapping).scrollIntoView();
  } else {
    /** We always want to append a block type */
    safeInsert(type.createAndFill(nodeAttributes))(tr).scrollIntoView();
  }
  return tr;
}
// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
export function getWrappingOptions(state, type,
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-explicit-any
nodeAttributes) {
  var _state$selection = state.selection,
    $from = _state$selection.$from,
    $to = _state$selection.$to,
    from = _state$selection.from;

  // Ignored via go/ees005
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  var range = $from.blockRange($to);
  var isMediaSelection = state.selection instanceof NodeSelection && state.selection.node.type === state.schema.nodes.media;

  /**
   * To wrap a media group we need to start the range from one position
   * before a media selection's from position.
   */
  if (isMediaSelection) {
    var prev = from - 1;
    range = state.doc.resolve(from > 0 ? prev : from).blockRange($to);
  }
  var isAllowedChild = true;
  /**
   * Added a check to avoid wrapping codeblock
   */
  if (state.selection.empty) {
    state.doc.nodesBetween($from.pos, $to.pos, function (node) {
      if (!isAllowedChild) {
        return false;
      }
      return isAllowedChild = node.type !== state.schema.nodes.codeBlock;
    });
  }
  // Ignored via go/ees005
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  var wrapping = isAllowedChild && range && findWrapping(range, type, nodeAttributes);
  return {
    range: range,
    wrapping: wrapping
  };
}