import { Fragment } from '@atlaskit/editor-prosemirror/model';

/** Rebuilds a list-like PM node from a flat array of items. */

/** Extracts top-level content nodes from an item being broken out past the root list. */

/**
 * Build a replacement Fragment from a flat array of items.
 *
 * Items with depth >= 0 are grouped and rebuilt via `rebuildFn`.
 * Items with depth < 0 are extracted via `extractContentFn`.
 */
export function buildReplacementFragment({
  items,
  schema,
  rebuildFn,
  extractContentFn
}) {
  let fragment = Fragment.empty;
  let pendingListSegment = [];
  let pendingStartIdx = 0;
  const contentStartOffsets = new Array(items.length);
  const flushListSegment = () => {
    if (pendingListSegment.length > 0) {
      const fragmentOffset = fragment.size;
      const result = rebuildFn(pendingListSegment, schema);
      if (result) {
        // Map the rebuild's content start offsets into the overall fragment.
        for (let i = 0; i < pendingListSegment.length; i++) {
          contentStartOffsets[pendingStartIdx + i] = fragmentOffset + result.contentStartOffsets[i];
        }
        fragment = fragment.addToEnd(result.node);
      }
      pendingListSegment = [];
    }
  };
  let elIdx = 0;
  for (const item of items) {
    if (item.depth < 0) {
      flushListSegment();
      // Extracted element — content children become top-level nodes.
      // Record offset of first content child.
      contentStartOffsets[elIdx] = fragment.size;
      for (const node of extractContentFn(item, schema)) {
        fragment = fragment.addToEnd(node);
      }
    } else {
      if (pendingListSegment.length === 0) {
        pendingStartIdx = elIdx;
      }
      pendingListSegment.push(item);
    }
    elIdx++;
  }
  flushListSegment();
  return {
    fragment,
    contentStartOffsets
  };
}