var __rest = this && this.__rest || function (s, e) {
  var t = {};
  for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
  if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
    if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];
  }
  return t;
};
/**
 * Our algorithm have additional one ghost item
 * whose index as `data.length` to simplify the calculation
 */
export const GHOST_ITEM_KEY = '__vc_ghost_item__';
/**
 * Safari has the elasticity effect which provides negative `scrollTop` value.
 * We should ignore it since will make scroll animation shake.
 */
export function alignScrollTop(scrollTop, scrollRange) {
  if (scrollTop < 0) {
    return 0;
  }
  if (scrollTop >= scrollRange) {
    return scrollRange;
  }
  return scrollTop;
}
/**
 * Get node `offsetHeight`. We prefer node is a dom element directly.
 * But if not provided, downgrade to `findDOMNode` to get the real dom element.
 */
export function getNodeHeight(node) {
  return node ? node.offsetHeight : 0;
}
/**
 * Calculate the located item absolute top with whole scroll height
 */
export function getItemAbsoluteTop(_a) {
  var {
      scrollTop
    } = _a,
    rest = __rest(_a, ["scrollTop"]);
  return scrollTop + getItemRelativeTop(rest);
}
/**
 * Calculate the located item related top with current window height
 */
export function getItemRelativeTop(_ref) {
  let {
    itemIndex,
    itemOffsetPtg,
    itemElementHeights,
    scrollPtg,
    clientHeight,
    getItemKey
  } = _ref;
  const locatedItemHeight = itemElementHeights[getItemKey(itemIndex)] || 0;
  const locatedItemTop = scrollPtg * clientHeight;
  const locatedItemOffset = itemOffsetPtg * locatedItemHeight;
  return Math.floor(locatedItemTop - locatedItemOffset);
}
export function getCompareItemRelativeTop(_ref2) {
  let {
    locatedItemRelativeTop,
    locatedItemIndex,
    compareItemIndex,
    startIndex,
    endIndex,
    getItemKey,
    itemElementHeights
  } = _ref2;
  let originCompareItemTop = locatedItemRelativeTop;
  const compareItemKey = getItemKey(compareItemIndex);
  if (compareItemIndex <= locatedItemIndex) {
    for (let index = locatedItemIndex; index >= startIndex; index -= 1) {
      const key = getItemKey(index);
      if (key === compareItemKey) {
        break;
      }
      const prevItemKey = getItemKey(index - 1);
      originCompareItemTop -= itemElementHeights[prevItemKey] || 0;
    }
  } else {
    for (let index = locatedItemIndex; index <= endIndex; index += 1) {
      const key = getItemKey(index);
      if (key === compareItemKey) {
        break;
      }
      originCompareItemTop += itemElementHeights[key] || 0;
    }
  }
  return originCompareItemTop;
}
export function getScrollPercentage(_ref3) {
  let {
    scrollTop,
    scrollHeight,
    clientHeight
  } = _ref3;
  if (scrollHeight <= clientHeight) {
    return 0;
  }
  const scrollRange = scrollHeight - clientHeight;
  const alignedScrollTop = alignScrollTop(scrollTop, scrollRange);
  const scrollTopPtg = alignedScrollTop / scrollRange;
  return scrollTopPtg;
}
export function getElementScrollPercentage(element) {
  if (!element) {
    return 0;
  }
  return getScrollPercentage(element);
}
/**
 * Get location item and its align percentage with the scroll percentage.
 * We should measure current scroll position to decide which item is the location item.
 * And then fill the top count and bottom count with the base of location item.
 *
 * `total` should be the real count instead of `total - 1` in calculation.
 */
function getLocationItem(scrollPtg, total) {
  const itemIndex = Math.floor(scrollPtg * total);
  const itemTopPtg = itemIndex / total;
  const itemBottomPtg = (itemIndex + 1) / total;
  const itemOffsetPtg = (scrollPtg - itemTopPtg) / (itemBottomPtg - itemTopPtg);
  return {
    index: itemIndex,
    offsetPtg: itemOffsetPtg
  };
}
/**
 * Get display items start, end, located item index. This is pure math calculation
 */
export function getRangeIndex(scrollPtg, itemCount, visibleCount) {
  const {
    index,
    offsetPtg
  } = getLocationItem(scrollPtg, itemCount);
  const beforeCount = Math.ceil(scrollPtg * visibleCount);
  const afterCount = Math.ceil((1 - scrollPtg) * visibleCount);
  return {
    itemIndex: index,
    itemOffsetPtg: offsetPtg,
    startIndex: Math.max(0, index - beforeCount),
    endIndex: Math.min(itemCount - 1, index + afterCount)
  };
}
export function requireVirtual(height, itemHeight, count, virtual) {
  return virtual !== false && typeof height === 'number' && count * itemHeight > height;
}