import React from 'react';
import { connect } from 'react-redux';
import { isEqual } from 'lodash';

import { fetchPostsBySection, fetchSavedPosts } from '../../actions/posts.js';
import { SAVED_TYPE } from '../../constants.js';

import LoadingIndicator from '../../../../components/LoadingIndicator.js';
import PostItem from './PostItem.js';

class PostList extends React.Component {
  lastPostRef = null;
  observer = null;

  constructor(props) {
    super(props);

    this.lastPostRef = React.createRef();

    const observerOptions = { root: null, rootMargin: '0px', threshold: 0 };
    this.observer = new IntersectionObserver(this.handleIntersect, observerOptions);
  }

  componentDidUpdate() {
    if (this.lastPostRef.current && !this.props.isFetching) {
      this.observer.observe(this.lastPostRef.current);
    }
  }

  componentWillUnmount() {
    this.observer.disconnect();
  }

  handleIntersect = entries => {
    entries.every(entry => {
      if (entry.isIntersecting) {
        this.observer.unobserve(entry.target);

        if (this.props.next && !this.props.lastReached) {
          this.paginate();
        }

        return false;
      }
    });
  };

  paginate() {
    if (this.props.selected.type === SAVED_TYPE) {
      this.props.fetchSavedPosts(this.props.next);
    } else {
      this.props.fetchPostsBySection(this.props.selected, this.props.next);
    }
  }

  render() {
    const isLastItem = this.props.postsByType.toReversed().find(item => !item.read);

    const postItems = this.props.postsByType.map((item, index) => {
      const defaultProps = {
        key: index,
        post: item,
        selected: this.props.selected,
        feedUrl: this.props.feedUrl,
      };

      if (isLastItem?.id === item.id) {
        return <PostItem {...defaultProps} forwardedRef={this.lastPostRef} />;
      } else {
        return <PostItem {...defaultProps} />;
      }
    });

    if (isEqual(this.props.selected, {})) {
      return (
        <div className="post-message">
          <div className="post-message__block">
            <i className="fas fa-arrow-left" />
            <p className="post-message__text">Select an item to show its unread posts</p>
          </div>
        </div>
      );
    } else if (postItems.length === 0 && !this.props.isFetching) {
      return (
        <div className="post-message">
          <div className="post-message__block">
            <p className="post-message__text">
              No unread posts from the selected section at this moment, try again later
            </p>
          </div>
        </div>
      );
    } else {
      return (
        <div className="posts" ref={this.props.forwardedRef}>
          <ul className="posts__list">{postItems}</ul>
          {this.props.isFetching && <LoadingIndicator />}
        </div>
      );
    }
  }
}

const mapStateToProps = state => ({
  isFetching: state.posts.isFetching,
  next: state.selected.next,
  lastReached: state.selected.lastReached,
  selected: state.selected.item,
});

const mapDispatchToProps = dispatch => ({
  fetchPostsBySection: (rule, next = false) => dispatch(fetchPostsBySection(rule, next)),
  fetchSavedPosts: (next = false) => dispatch(fetchSavedPosts(next)),
});

export default connect(mapStateToProps, mapDispatchToProps, null, { forwardRef: true })(
  PostList
);
