import {
  ReachBottomListener,
  ReachBottomListenerParams,
  ScrollableWindow,
} from '../reach-bottom-listener';
import { CollectionState, FiltersMap, PartialLodash } from '@wix/bex-core';

export interface CollectionReachBottomParams<
  T,
  F extends FiltersMap = FiltersMap,
> {
  collection: CollectionState<T, F>;
  reachBottomParams?: Partial<ReachBottomListenerParams>;
  lodash: PartialLodash;
}

export class CollectionReachBottom<T, F extends FiltersMap = FiltersMap> {
  collection: CollectionState<T, F>;
  reachBottom: ReachBottomListener;

  constructor(params: CollectionReachBottomParams<T, F>) {
    const { reachBottomParams, lodash } = params;
    this.collection = params.collection;

    this.reachBottom = new ReachBottomListener({
      onReachBottom: this.collection.fetchNextPageIfNeeded,
      delay: 200,
      // this constance is a naive heuristic: amount of pixels covered in 250ms (avg server latency) when scrolling 1 pixel per millisecond (avg scrolling speed)
      offsetPX: 250,
      lodash,
      ...reachBottomParams,
      container: reachBottomParams?.container ?? new ScrollableWindow(),
    });
  }

  triggerListenerIfReached = () => {
    return this.reachBottom.triggerListenerIfReached();
  };

  waitForScrollIdle = () => {
    const { reachBottom } = this;
    // if currently scrolling, return a promise for when the scrolling is idle
    if (!reachBottom.isScrolling) {
      return;
    }
    return new Promise((resolve) => {
      reachBottom.events.once('idle', resolve);
    });
  };

  subscribe() {
    const { reachBottom } = this;
    reachBottom.subscribe();
  }

  unsubscribe() {
    const { reachBottom, collection } = this;
    collection.beforeSetData = undefined;
    reachBottom.unsubscribe();
  }
}
