import React from 'react';
import NavigationActions from 'react-navigation';
import { ActivityIndicator, FlatList, Text, TouchableOpacity, View } from 'react-native';
import { MATURE_TAGS, normalizeURI, createNormalizedClaimSearchKey } from 'lbry-redux';
import _ from 'lodash';
import FileItem from 'component/fileItem';
import FileListItem from 'component/fileListItem';
import Icon from 'react-native-vector-icons/FontAwesome5';
import Colors from 'styles/colors';
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
import claimListStyle from 'styles/claimList';
import discoverStyle from 'styles/discover';
import moment from 'moment';

const horizontalLimit = 7;
const softLimit = 500;

class ClaimList extends React.PureComponent {
  scrollView = null;

  state = {
    currentPage: 1, // initial page load is page 1
    subscriptionsView: false, // whether or not this claim list is for subscriptions
    lastPageReached: false,
  };

  componentDidMount() {
    const { channelIds } = this.props;

    if (channelIds) {
      this.setState({ subscriptionsView: true });
    }

    this.doClaimSearch();
  }

  componentDidUpdate(prevProps) {
    const {
      claimSearchByQuery: prevClaimSearchByQuery,
      orderBy: prevOrderBy,
      searchByTags,
      tags: prevTags,
      channelIds: prevChannelIds,
      time: prevTime,
    } = prevProps;
    const { claimSearchByQuery, orderBy, tags, channelIds, time } = this.props;

    if (
      !_.isEqual(orderBy, prevOrderBy) ||
      !_.isEqual(tags, prevTags) ||
      !_.isEqual(channelIds, prevChannelIds) ||
      time !== prevTime
    ) {
      // reset to page 1 because the order, tags or channelIds changed
      this.setState({ currentPage: 1 }, () => {
        if (this.scrollView) {
          this.scrollView.scrollToOffset({ animated: true, offset: 0 });
        }

        if (prevChannelIds && channelIds) {
          if (channelIds) {
            this.setState({ subscriptionsView: true });
          }
        } else if (tags && tags.length > 0) {
          this.setState({ subscriptionsView: false });
        }

        this.doClaimSearch();
      });
    }
  }

  buildClaimSearchOptions() {
    const { orderBy, channelIds, showNsfwContent, tags, time } = this.props;
    const { currentPage, subscriptionsView } = this.state;

    const options = {
      order_by: orderBy,
      no_totals: true,
      page: currentPage,
      page_size: Constants.DEFAULT_PAGE_SIZE,
    };

    if (channelIds) {
      options.channel_ids = channelIds;
    } else if (tags && tags.length > 0) {
      options.any_tags = tags;
    }
    if (!showNsfwContent) {
      options.not_tags = MATURE_TAGS;
    }

    if (orderBy && orderBy[0] === Constants.ORDER_BY_EFFECTIVE_AMOUNT && Constants.TIME_ALL !== time) {
      options.release_time = this.getReleaseTimeOption(time);
    }

    return options;
  }

  getReleaseTimeOption = time => {
    return `>${Math.floor(
      moment()
        .subtract(1, time)
        .unix()
    )}`;
  };

  doClaimSearch() {
    const { claimSearch } = this.props;
    const options = this.buildClaimSearchOptions();
    claimSearch(options);
  }

  handleVerticalEndReached = () => {
    // fetch more content
    const { claimSearchByQuery, lastPageReached } = this.props;

    const options = this.buildClaimSearchOptions();
    const claimSearchKey = createNormalizedClaimSearchKey(options);
    const uris = claimSearchByQuery[claimSearchKey];
    if (
      lastPageReached[claimSearchKey] ||
      ((uris.length > 0 && uris.length < Constants.DEFAULT_PAGE_SIZE) || uris.length >= softLimit)
    ) {
      return;
    }

    this.setState({ currentPage: this.state.currentPage + 1 }, () => this.doClaimSearch());
  };

  appendMorePlaceholder = items => {
    items.push(Constants.MORE_PLACEHOLDER);
    return items;
  };

  onMorePressed = () => {
    const { navigation, tags } = this.props;

    // tags.length > 1 means this is the Trending list
    if (tags.length === 1) {
      navigation.navigate({ routeName: Constants.DRAWER_ROUTE_TAG, key: 'tagPage', params: { tag: tags[0] } });
    } else {
      navigation.navigate({ routeName: Constants.DRAWER_ROUTE_TRENDING, params: { filterForTags: true } });
    }
  };

  renderMorePlaceholder = () => {
    return (
      <TouchableOpacity style={discoverStyle.fileItemMore} onPress={this.onMorePressed}>
        <Text style={discoverStyle.moreText}>more</Text>
        <Icon style={discoverStyle.moreIcon} name={'angle-double-down'} color={Colors.White} size={16} />
      </TouchableOpacity>
    );
  };

  verticalListEmptyComponent = () => {
    return (
      <Text style={claimListStyle.noContentText}>No content to display at this time. Please check back later.</Text>
    );
  };

  renderVerticalItem = ({ item }) => {
    const { hideChannel, navigation } = this.props;
    return (
      <FileListItem
        key={item}
        uri={item}
        hideChannel={hideChannel}
        style={claimListStyle.verticalListItem}
        navigation={navigation}
      />
    );
  };

  renderHorizontalItem = ({ item }) => {
    const { navigation } = this.props;

    return item === Constants.MORE_PLACEHOLDER ? (
      this.renderMorePlaceholder()
    ) : (
      <FileItem
        style={discoverStyle.fileItem}
        mediaStyle={discoverStyle.fileItemMedia}
        key={item}
        uri={normalizeURI(item)}
        navigation={navigation}
        showDetails
        compactView={false}
      />
    );
  };

  render() {
    const {
      ListHeaderComponent,
      loading,
      morePlaceholder,
      navigation,
      orientation = Constants.ORIENTATION_VERTICAL,
      style,
      claimSearchByQuery,
    } = this.props;
    const { subscriptionsView } = this.state;

    const options = this.buildClaimSearchOptions();
    const claimSearchKey = createNormalizedClaimSearchKey(options);
    let uris = claimSearchByQuery[claimSearchKey];

    if (uris) {
      uris = uris.filter(uri => uri && uri.length > 0);
    }

    if (Constants.ORIENTATION_VERTICAL === orientation) {
      return (
        <View style={style}>
          <FlatList
            ref={ref => {
              this.scrollView = ref;
            }}
            ListHeaderComponent={ListHeaderComponent}
            ListEmptyComponent={loading ? null : this.verticalListEmptyComponent}
            style={claimListStyle.verticalScrollContainer}
            contentContainerStyle={claimListStyle.verticalScrollPadding}
            initialNumToRender={10}
            maxToRenderPerBatch={20}
            removeClippedSubviews
            renderItem={this.renderVerticalItem}
            data={uris}
            keyExtractor={(item, index) => item}
            onEndReached={this.handleVerticalEndReached}
            onEndReachedThreshold={0.2}
          />
          {loading && (
            <View style={claimListStyle.verticalLoading}>
              <ActivityIndicator size={'small'} color={Colors.NextLbryGreen} />
            </View>
          )}
        </View>
      );
    }

    if (Constants.ORIENTATION_HORIZONTAL === orientation) {
      if (loading) {
        return (
          <View style={discoverStyle.listLoading}>
            <ActivityIndicator size={'small'} color={Colors.NextLbryGreen} />
          </View>
        );
      }

      return (
        <FlatList
          style={style || claimListStyle.horizontalScrollContainer}
          contentContainerStyle={claimListStyle.horizontalScrollPadding}
          initialNumToRender={3}
          maxToRenderPerBatch={3}
          removeClippedSubviews
          renderItem={this.renderHorizontalItem}
          horizontal
          showsHorizontalScrollIndicator={false}
          data={uris ? this.appendMorePlaceholder(uris.slice(0, horizontalLimit)) : []}
          keyExtractor={(item, index) => item}
        />
      );
    }

    return null;
  }
}

export default ClaimList;