content: import { debounce } from 'lodash';
  import React from 'react';
  import ImmutablePropTypes from 'react-immutable-proptypes';
  import PropTypes from 'prop-types';
  import StatusContainer from '../containers/status_container';
  import ImmutablePureComponent from 'react-immutable-pure-component';
  import LoadGap from './load_gap';
  import ScrollableList from './scrollable_list';
  import RegenerationIndicator from 'mastodon/components/regeneration_indicator';
  
  export default class StatusList extends ImmutablePureComponent {
  
    static propTypes = {
      scrollKey: PropTypes.string.isRequired,
      statusIds: ImmutablePropTypes.list.isRequired,
      featuredStatusIds: ImmutablePropTypes.list,
      onLoadMore: PropTypes.func,
      onScrollToTop: PropTypes.func,
      onScroll: PropTypes.func,
      trackScroll: PropTypes.bool,
      isLoading: PropTypes.bool,
      isPartial: PropTypes.bool,
      hasMore: PropTypes.bool,
      prepend: PropTypes.node,
      emptyMessage: PropTypes.node,
      alwaysPrepend: PropTypes.bool,
      timelineId: PropTypes.string,
    };
  
    static defaultProps = {
      trackScroll: true,
    };
  
    getFeaturedStatusCount = () => {
      return this.props.featuredStatusIds ? this.props.featuredStatusIds.size : 0;
    }
  
    getCurrentStatusIndex = (id, featured) => {
      if (featured) {
        return this.props.featuredStatusIds.indexOf(id);
      } else {
        return this.props.statusIds.indexOf(id) + this.getFeaturedStatusCount();
      }
    }
  
    handleMoveUp = (id, featured) => {
      const elementIndex = this.getCurrentStatusIndex(id, featured) - 1;
      this._selectChild(elementIndex, true);
    }
  
    handleMoveDown = (id, featured) => {
      const elementIndex = this.getCurrentStatusIndex(id, featured) + 1;
      this._selectChild(elementIndex, false);
    }
  
    handleLoadOlder = debounce(() => {
      this.props.onLoadMore(this.props.statusIds.size > 0 ? this.props.statusIds.last() : undefined);
    }, 300, { leading: true })
  
    _selectChild (index, align_top) {
      const container = this.node.node;
      const element = container.querySelector(`article:nth-of-type(${index + 1}) .focusable`);
  
      if (element) {
        if (align_top && container.scrollTop > element.offsetTop) {
          element.scrollIntoView(true);
        } else if (!align_top && container.scrollTop + container.clientHeight < element.offsetTop + element.offsetHeight) {
          element.scrollIntoView(false);
        }
        element.focus();
      }
    }
  
    setRef = c => {
      this.node = c;
    }
  
    render () {
      const { statusIds, featuredStatusIds, onLoadMore, timelineId, ...other }  = this.props;
      const { isLoading, isPartial } = other;
  
      if (isPartial) {
        return <RegenerationIndicator />;
      }
  
      let scrollableContent = (isLoading || statusIds.size > 0) ? (
        statusIds.map((statusId, index) => statusId === null ? (
          <LoadGap
            key={'gap:' + statusIds.get(index + 1)}
            disabled={isLoading}
            maxId={index > 0 ? statusIds.get(index - 1) : null}
            onClick={onLoadMore}
          />
        ) : (
          <StatusContainer
            key={statusId}
            id={statusId}
            onMoveUp={this.handleMoveUp}
            onMoveDown={this.handleMoveDown}
            contextType={timelineId}
            scrollKey={this.props.scrollKey}
            showThread
          />
        ))
      ) : null;
  
      if (scrollableContent && featuredStatusIds) {
        scrollableContent = featuredStatusIds.map(statusId => (
          <StatusContainer
            key={`f-${statusId}`}
            id={statusId}
            featured
            onMoveUp={this.handleMoveUp}
            onMoveDown={this.handleMoveDown}
            contextType={timelineId}
            showThread
          />
        )).concat(scrollableContent);
      }
  
      return (
        <ScrollableList {...other} showLoading={isLoading && statusIds.size === 0} onLoadMore={onLoadMore && this.handleLoadOlder} ref={this.setRef}>
          {scrollableContent}
        </ScrollableList>
      );
    }
  
  }
  