function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
// @ts-nocheck
import React, { useCallback, useRef, useEffect, useMemo } from "react";
import { View, Dimensions } from "react-native";
import CustomError from "./errors/CustomError";
import ExceptionList from "./errors/ExceptionList";
import FlashList from "./FlashList";
import { applyContentContainerInsetForLayoutManager } from "./utils/ContentContainerUtils";
const defaultEstimatedItemSize = 100;

/**
 * MasonryFlashListRef with support for scroll related methods
 */

/**
 * FlashList variant that enables rendering of masonry layouts.
 * If you want `MasonryFlashList` to optimize item arrangement, enable `optimizeItemArrangement` and pass a valid `overrideItemLayout` function.
 */
const MasonryFlashListComponent = /*#__PURE__*/React.forwardRef((props, forwardRef) => {
  var _ref, _props$estimatedListS, _dataSet$0$length, _dataSet$, _props$estimatedItemS;
  const columnCount = props.numColumns || 1;
  const drawDistance = props.drawDistance;
  const estimatedListSize = (_ref = (_props$estimatedListS = props.estimatedListSize) !== null && _props$estimatedListS !== void 0 ? _props$estimatedListS : Dimensions.get("window")) !== null && _ref !== void 0 ? _ref : {
    height: 500,
    width: 500
  };
  if (props.optimizeItemArrangement && !props.overrideItemLayout) {
    throw new CustomError(ExceptionList.overrideItemLayoutRequiredForMasonryOptimization);
  }
  const dataSet = useDataSet(columnCount, Boolean(props.optimizeItemArrangement), props.data, props.overrideItemLayout, props.extraData);
  const totalColumnFlex = useTotalColumnFlex(dataSet, props);
  const onScrollRef = useRef([]);
  const emptyScrollEvent = useRef(getEmptyScrollEvent()).current;
  const ScrollComponent = useRef(getFlashListScrollView(onScrollRef, () => {
    var _getListRenderedSize;
    return ((_getListRenderedSize = getListRenderedSize(parentFlashList)) === null || _getListRenderedSize === void 0 ? void 0 : _getListRenderedSize.height) || estimatedListSize.height;
  })).current;
  const onScrollProxy = useRef(scrollEvent => {
    var _parentFlashList$curr, _parentFlashList$curr2, _onScrollRef$current;
    emptyScrollEvent.nativeEvent.contentOffset.y = scrollEvent.nativeEvent.contentOffset.y - ((_parentFlashList$curr = (_parentFlashList$curr2 = parentFlashList.current) === null || _parentFlashList$curr2 === void 0 ? void 0 : _parentFlashList$curr2.firstItemOffset) !== null && _parentFlashList$curr !== void 0 ? _parentFlashList$curr : 0);
    (_onScrollRef$current = onScrollRef.current) === null || _onScrollRef$current === void 0 ? void 0 : _onScrollRef$current.forEach(onScrollCallback => {
      onScrollCallback === null || onScrollCallback === void 0 ? void 0 : onScrollCallback(emptyScrollEvent);
    });
    if (!scrollEvent.nativeEvent.doNotPropagate) {
      var _props$onScroll;
      (_props$onScroll = props.onScroll) === null || _props$onScroll === void 0 ? void 0 : _props$onScroll.call(props, scrollEvent);
    }
  }).current;

  /**
   * We're triggering an onScroll on internal lists so that they register the correct offset which is offset - header size.
   * This will make sure viewability callbacks are triggered correctly.
   * 32 ms is equal to two frames at 60 fps. Faster framerates will not cause any problems.
   */
  const onLoadForNestedLists = useRef(args => {
    var _props$onLoad;
    setTimeout(() => {
      emptyScrollEvent.nativeEvent.doNotPropagate = true;
      onScrollProxy === null || onScrollProxy === void 0 ? void 0 : onScrollProxy(emptyScrollEvent);
      emptyScrollEvent.nativeEvent.doNotPropagate = false;
    }, 32);
    (_props$onLoad = props.onLoad) === null || _props$onLoad === void 0 ? void 0 : _props$onLoad.call(props, args);
  }).current;
  const [parentFlashList, getFlashList] = useRefWithForwardRef(forwardRef);
  const {
    renderItem,
    getItemType,
    getColumnFlex,
    overrideItemLayout,
    viewabilityConfig,
    keyExtractor,
    onLoad,
    onViewableItemsChanged,
    data,
    stickyHeaderIndices,
    CellRendererComponent,
    ItemSeparatorComponent,
    ...remainingProps
  } = props;
  const firstColumnHeight = ((_dataSet$0$length = (_dataSet$ = dataSet[0]) === null || _dataSet$ === void 0 ? void 0 : _dataSet$.length) !== null && _dataSet$0$length !== void 0 ? _dataSet$0$length : 0) * ((_props$estimatedItemS = props.estimatedItemSize) !== null && _props$estimatedItemS !== void 0 ? _props$estimatedItemS : defaultEstimatedItemSize);
  const insetForLayoutManager = applyContentContainerInsetForLayoutManager({
    height: 0,
    width: 0
  }, props.contentContainerStyle, false);
  return /*#__PURE__*/React.createElement(FlashList, _extends({
    ref: getFlashList
  }, remainingProps, {
    horizontal: false,
    numColumns: columnCount,
    data: dataSet,
    onScroll: onScrollProxy,
    estimatedItemSize: firstColumnHeight || estimatedListSize.height,
    renderItem: args => {
      var _getListRenderedSize2, _getColumnFlex;
      return /*#__PURE__*/React.createElement(FlashList, {
        renderScrollComponent: ScrollComponent,
        estimatedItemSize: props.estimatedItemSize,
        data: args.item,
        onLoad: args.index === 0 ? onLoadForNestedLists : undefined,
        renderItem: innerArgs => {
          var _renderItem;
          return (_renderItem = renderItem === null || renderItem === void 0 ? void 0 : renderItem({
            ...innerArgs,
            item: innerArgs.item.originalItem,
            index: innerArgs.item.originalIndex,
            columnSpan: 1,
            columnIndex: args.index
          })) !== null && _renderItem !== void 0 ? _renderItem : null;
        },
        keyExtractor: keyExtractor ? (item, _) => {
          return keyExtractor === null || keyExtractor === void 0 ? void 0 : keyExtractor(item.originalItem, item.originalIndex);
        } : undefined,
        getItemType: getItemType ? (item, _, extraData) => {
          return getItemType === null || getItemType === void 0 ? void 0 : getItemType(item.originalItem, item.originalIndex, extraData);
        } : undefined,
        drawDistance: drawDistance,
        estimatedListSize: {
          height: estimatedListSize.height,
          width: ((((_getListRenderedSize2 = getListRenderedSize(parentFlashList)) === null || _getListRenderedSize2 === void 0 ? void 0 : _getListRenderedSize2.width) || estimatedListSize.width) + insetForLayoutManager.width) / totalColumnFlex * ((_getColumnFlex = getColumnFlex === null || getColumnFlex === void 0 ? void 0 : getColumnFlex(args.item, args.index, columnCount, props.extraData)) !== null && _getColumnFlex !== void 0 ? _getColumnFlex : 1)
        },
        extraData: props.extraData,
        CellRendererComponent: CellRendererComponent,
        ItemSeparatorComponent: ItemSeparatorComponent,
        viewabilityConfig: viewabilityConfig,
        onViewableItemsChanged: onViewableItemsChanged ? info => {
          updateViewTokens(info.viewableItems);
          updateViewTokens(info.changed);
          onViewableItemsChanged === null || onViewableItemsChanged === void 0 ? void 0 : onViewableItemsChanged(info);
        } : undefined,
        overrideItemLayout: overrideItemLayout ? (layout, item, _, __, extraData) => {
          overrideItemLayout === null || overrideItemLayout === void 0 ? void 0 : overrideItemLayout(layout, item.originalItem, item.originalIndex, columnCount, extraData);
          layout.span = undefined;
        } : undefined
      });
    },
    overrideItemLayout: getColumnFlex ? (layout, item, index, maxColumns, extraData) => {
      layout.span = columnCount * getColumnFlex(item, index, maxColumns, extraData) / totalColumnFlex;
    } : undefined
  }));
});

/**
 * Splits data for each column's FlashList
 */
const useDataSet = (columnCount, optimizeItemArrangement, sourceData, overrideItemLayout, extraData) => {
  return useMemo(() => {
    if (!sourceData || sourceData.length === 0) {
      return [];
    }
    const columnHeightTracker = new Array(columnCount).fill(0);
    const layoutObject = {
      size: undefined
    };
    const dataSet = new Array(columnCount);
    const dataSize = sourceData.length;
    for (let i = 0; i < columnCount; i++) {
      dataSet[i] = [];
    }
    for (let i = 0; i < dataSize; i++) {
      let nextColumnIndex = i % columnCount;
      if (optimizeItemArrangement) {
        var _layoutObject$size;
        for (let j = 0; j < columnCount; j++) {
          if (columnHeightTracker[j] < columnHeightTracker[nextColumnIndex]) {
            nextColumnIndex = j;
          }
        }
        // update height of column
        layoutObject.size = undefined;
        overrideItemLayout(layoutObject, sourceData[i], i, columnCount, extraData);
        columnHeightTracker[nextColumnIndex] += (_layoutObject$size = layoutObject.size) !== null && _layoutObject$size !== void 0 ? _layoutObject$size : defaultEstimatedItemSize;
      }
      dataSet[nextColumnIndex].push({
        originalItem: sourceData[i],
        originalIndex: i
      });
    }
    return dataSet;
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [sourceData, columnCount, optimizeItemArrangement, extraData]);
};
const useTotalColumnFlex = (dataSet, props) => {
  return useMemo(() => {
    const columnCount = props.numColumns || 1;
    if (!props.getColumnFlex) {
      return columnCount;
    }
    let totalFlexSum = 0;
    const dataSize = dataSet.length;
    for (let i = 0; i < dataSize; i++) {
      totalFlexSum += props.getColumnFlex(dataSet[i], i, columnCount, props.extraData);
    }
    return totalFlexSum;
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [dataSet, props.getColumnFlex, props.extraData]);
};

/**
 * Handle both function refs and refs with current property
 */
const useRefWithForwardRef = forwardRef => {
  const ref = useRef(null);
  return [ref, useCallback(instance => {
    ref.current = instance;
    if (typeof forwardRef === "function") {
      forwardRef(instance);
    } else if (forwardRef) {
      forwardRef.current = instance;
    }
  }, [forwardRef])];
};

/**
 * This ScrollView is actually just a view mimicking a scrollview. We block the onScroll event from being passed to the parent list directly.
 * We manually drive onScroll from the parent and thus, achieve recycling.
 */
const getFlashListScrollView = (onScrollRef, getParentHeight) => {
  const FlashListScrollView = /*#__PURE__*/React.forwardRef((props, ref) => {
    const {
      onLayout,
      onScroll,
      ...rest
    } = props;
    const onLayoutProxy = useCallback(layoutEvent => {
      onLayout === null || onLayout === void 0 ? void 0 : onLayout({
        nativeEvent: {
          layout: {
            height: getParentHeight(),
            width: layoutEvent.nativeEvent.layout.width
          }
        }
      });
    }, [onLayout]);
    useEffect(() => {
      if (onScroll) {
        var _onScrollRef$current2;
        (_onScrollRef$current2 = onScrollRef.current) === null || _onScrollRef$current2 === void 0 ? void 0 : _onScrollRef$current2.push(onScroll);
      }
      return () => {
        if (!onScrollRef.current || !onScroll) {
          return;
        }
        const indexToDelete = onScrollRef.current.indexOf(onScroll);
        if (indexToDelete > -1) {
          onScrollRef.current.splice(indexToDelete, 1);
        }
      };
    }, [onScroll]);
    return /*#__PURE__*/React.createElement(View, _extends({
      ref: ref
    }, rest, {
      onLayout: onLayoutProxy
    }));
  });
  FlashListScrollView.displayName = "FlashListScrollView";
  return FlashListScrollView;
};
const updateViewTokens = tokens => {
  const length = tokens.length;
  for (let i = 0; i < length; i++) {
    const token = tokens[i];
    if (token.index !== null && token.index !== undefined) {
      if (token.item) {
        token.index = token.item.originalIndex;
        token.item = token.item.originalItem;
      } else {
        token.index = null;
        token.item = undefined;
      }
    }
  }
};
const getEmptyScrollEvent = () => {
  return {
    nativeEvent: {
      contentOffset: {
        y: 0,
        x: 0
      }
    }
  };
};
const getListRenderedSize = parentFlashList => {
  var _parentFlashList$curr3, _parentFlashList$curr4;
  return parentFlashList === null || parentFlashList === void 0 ? void 0 : (_parentFlashList$curr3 = parentFlashList.current) === null || _parentFlashList$curr3 === void 0 ? void 0 : (_parentFlashList$curr4 = _parentFlashList$curr3.recyclerlistview_unsafe) === null || _parentFlashList$curr4 === void 0 ? void 0 : _parentFlashList$curr4.getRenderedSize();
};
MasonryFlashListComponent.displayName = "MasonryFlashList";

/**
 * FlashList variant that enables rendering of masonry layouts.
 * If you want `MasonryFlashList` to optimize item arrangement, enable `optimizeItemArrangement` and pass a valid `overrideItemLayout` function.
 */
export const MasonryFlashList = MasonryFlashListComponent;
//# sourceMappingURL=MasonryFlashList.js.map