// @flow
import getScrollParent from './getScrollParent';
import getParentNode from './getParentNode';
import getWindow from './getWindow';
import type { Window, VisualViewport } from '../types';
import isScrollParent from './isScrollParent';

/*
given a DOM element, return the list of all scroll parents, up the list of ancesors
until we get to the top window object. This list is what we attach scroll listeners
to, because if any of these parent elements scroll, we'll need to re-calculate the
reference element's position.
*/
export default function listScrollParents(
  element: Node,
  list: Array<Element | Window> = []
): Array<Element | Window | VisualViewport> {
  const scrollParent = getScrollParent(element);
  const isBody = scrollParent === element.ownerDocument?.body;
  const win = getWindow(scrollParent);
  const target = isBody
    ? [win].concat(
        win.visualViewport || [],
        isScrollParent(scrollParent) ? scrollParent : []
      )
    : scrollParent;
  const updatedList = list.concat(target);

  return isBody
    ? updatedList
    : // $FlowFixMe[incompatible-call]: isBody tells us target will be an HTMLElement here
      updatedList.concat(listScrollParents(getParentNode(target)));
}
