import React, { createRef, PureComponent } from 'react';
// import { withNavigation } from 'react-navigation';
import { Subscription } from 'rxjs';
import { auditTime } from 'rxjs/operators';
import { withVirtualization } from '../hoc/with-virtualization';
import { fp as _ } from '../utils/fp';
import { SBox } from '../s-components/layout/s-box';
import { SwipeablePlaylistItem } from './swipeable-playlist-item';
import {
  getKeyComposed,
  isVirtualElement,
  mutableRemoveOldRefs,
} from '../transducers';
import {
  scrollableListSubject$,
  scrollNamedSubject$,
} from '../utils/scroll-service';
import { getSwipeableOptionsByVariant } from '../submodules/starring-playlists/transducers';
import { PLAYLIST_PAGE_VARIANT } from '../submodules/starring-playlists/constants';
import { TPlaylist } from '../submodules/starring-playlists/types';
import { SwipeablePlaylistCard } from './swipeable-playlist-card';

type TProps = {
  cards: TPlaylist[];
  onPress: (...args: any[]) => void;
  onPressRight: (...args: any[]) => void;
  pageVariant: PLAYLIST_PAGE_VARIANT;
  cardHeight: number;
  hiddenFromTopCount: number;
  maxVisible: number;
  keepVisibleCount: number;
  variant?: string;
  composedKey?: string[];
  starSource: string;
  cardVariant: string;
};

type TState = {
  active: string | null;
};

export class SwipeablePlaylistComponent extends PureComponent<TProps, TState> {
  state = {
    active: null,
  };

  swipeRefs: Record<string, any> = {};

  scrollWatcher?: Subscription;

  scrollWatcher2?: Subscription;

  static defaultProps = {
    variant: 'dark',
  };

  componentDidMount() {
    this.scrollWatcher = scrollNamedSubject$
      .pipe(auditTime(500))
      .subscribe(this.closeActive);

    this.scrollWatcher2 = scrollableListSubject$
      .pipe(auditTime(500))
      .subscribe(this.closeActive);
  }

  componentDidUpdate({ cards: oldCards }: TProps) {
    const { cards, composedKey } = this.props;
    if (cards !== oldCards) {
      mutableRemoveOldRefs(cards, this.swipeRefs, composedKey, 'id');
    }
  }

  componentWillUnmount() {
    if (this.scrollWatcher) {
      this.scrollWatcher.unsubscribe();
    }
    if (this.scrollWatcher2) {
      this.scrollWatcher2.unsubscribe();
    }
  }

  onPressHandler = (...args: any[]) => {
    const { onPress } = this.props;
    this.closeActive();

    // TODO try to do https://facebook.github.io/react-native/docs/performance#my-touchablex-view-isnt-very-responsive
    if (_.isFunction(onPress)) {
      onPress(...args);
    }
  };

  onPressRightHandler = (...args: any[]) => {
    const { onPressRight } = this.props;
    onPressRight(...args);
    this.closeActive();
  };

  onSwipeableRightWillOpenHandler = (keyComposed: string) => {
    const { active } = this.state;
    const { swipeRefs } = this;
    if (active && active !== keyComposed && swipeRefs[active!]) {
      const { current } = swipeRefs[active!] as any;
      if (current && _.isFunction(current.close)) {
        current.close();
      }
    }
    this.setState({ active: keyComposed });
  };

  closeActive = () => {
    const { active } = this.state;

    if (active) {
      const { swipeRefs } = this;
      this.setState({ active: null });
      if (swipeRefs[active!]) {
        const { current } = swipeRefs[active!] as any;
        if (current && _.isFunction(current.close)) {
          current.close();
        }
      }
    }
  };

  renderItem = (item: TPlaylist, i: number) => {
    const {
      cardHeight,
      variant,
      hiddenFromTopCount,
      maxVisible,
      keepVisibleCount,
      composedKey,
      pageVariant,
      starSource,
      cardVariant,
    } = this.props;
    const { swipeRefs } = this;
    const keyComposed = getKeyComposed(composedKey, 'id')(item);

    if (!swipeRefs[keyComposed]) {
      swipeRefs[keyComposed] = createRef();
    }

    if (isVirtualElement(i, hiddenFromTopCount, maxVisible, keepVisibleCount)) {
      return null;
    }

    if (variant === 'playlists-card') {
      return (
        <SwipeablePlaylistCard
          {...getSwipeableOptionsByVariant(pageVariant)}
          key={keyComposed}
          ref={swipeRefs[keyComposed]}
          keyComposed={keyComposed}
          {...item}
          cardHeight={cardHeight}
          variant={variant!}
          onPress={this.onPressHandler}
          onPressRight={this.onPressRightHandler}
          onSwipeableRightWillOpen={this.onSwipeableRightWillOpenHandler}
          cardVariant={cardVariant}
          starSource={starSource}
        />
      );
    }

    return (
      <SwipeablePlaylistItem
        {...getSwipeableOptionsByVariant(pageVariant)}
        key={keyComposed}
        ref={swipeRefs[keyComposed]}
        keyComposed={keyComposed}
        {...item}
        cardHeight={cardHeight}
        variant={variant!}
        onPress={this.onPressHandler}
        onPressRight={this.onPressRightHandler}
        onSwipeableRightWillOpen={this.onSwipeableRightWillOpenHandler}
        starSource={starSource}
      />
    );
  };

  render() {
    const { cards, cardHeight, hiddenFromTopCount } = this.props;
    return (
      <SBox
        testID="swipeable-playlist"
        height={cardHeight * cards.length}
        pt={cardHeight * hiddenFromTopCount}
      >
        {cards.map(this.renderItem)}
      </SBox>
    );
  }
}

export const SwipeablePlaylist = _.compose(
  // withNavigation,
  withVirtualization
)(SwipeablePlaylistComponent);
