import React from 'react';
import PropTypes from 'prop-types';
import scrollHelper from './scrollHelper';

export default class ListProvider extends React.Component {
  static propTypes = {
    children: PropTypes.func.isRequired,
    clipResultsAt: PropTypes.number.isRequired,
    dataIn: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
    onHrefPrint: PropTypes.func.isRequired,
    onSelect: PropTypes.func.isRequired,
    itemSearch: PropTypes.func.isRequired,
    shouldReset: PropTypes.bool
  };

  static defaultProps = {
    shouldReset: false
  };

  constructor(props) {
    super(props);
    this.state = {
      searchTerm: '',
      highlightIndex: 0
    };
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.shouldReset === true && this.props.shouldReset === false) {
      this.setHighlightIndex(0);
      this.clearSearch();
    }
  }

  onChange = (e) => {
    this.setState({ searchTerm: e.target.value, highlightIndex: 0 },
      this.setScrollTop(this.dropdownRef)
    );
  }

  onArrowDown = (size, cb) => {
    this.setState({ highlightIndex: (this.state.highlightIndex + 1) % size }, cb);
  }

  onArrowUp = (size, cb) => {
    // TODO? use % size to remove if
    let next = this.state.highlightIndex - 1;
    if (next < 0) {
      next = size - 1;
    }
    this.setState({ highlightIndex: next }, cb);
  }

  onKeyDown = (size, currentOption) => (e) => {
    switch (e.key) {
      case 'ArrowDown':
        e.preventDefault();
        this.onArrowDown(size, this.onVerticalMovement(this.dropdownRef));
        break;
      case 'ArrowUp':
        e.preventDefault();
        this.onArrowUp(size, this.onVerticalMovement(this.dropdownRef));
        break;
      case 'Enter':
        if (this.props.onHrefPrint(currentOption)) {
          window.location.assign(this.props.onHrefPrint(currentOption))
        } else {
          this.props.onSelect(currentOption);
        }
        break;
      default:
        break;
    }
  }

  onVerticalMovement = (dropdownRef) => () => {
    if (!dropdownRef) { return; }
    if (!dropdownRef.listRef || !dropdownRef.highlightedItemRef) { return; }
    const list = dropdownRef.listRef;
    const item = dropdownRef.highlightedItemRef;
    scrollHelper(
      list,
      item.offsetTop - (item.clientHeight * 0.5) - (list.clientHeight / 2),
      -50
    );
  }

  setScrollTop = (dropdownRef, to = 0) => () => {
    if (!dropdownRef) { return; }
    if (!dropdownRef.listRef) { return; }
    dropdownRef.listRef.scrollTop = to;
  }

  setHighlightIndex = (to = 0) => {
    this.setState({ highlightIndex: to });
  }

  clearSearch = () => {
    this.setState({ searchTerm: '' }, this.setScrollTop(this.dropdownRef));
  }

  render() {
    const { children, clipResultsAt, dataIn, itemSearch } = this.props;
    const { searchTerm, highlightIndex } = this.state;

    const data = dataIn.filter(item => itemSearch(searchTerm, item));

    return children({
      searchTerm,
      highlightIndex,
      data: data.slice(0, clipResultsAt),
      didClipData: data.length > clipResultsAt
    }, {
      clearSearch: this.clearSearch,
      onChange: this.onChange,
      onKeyDown: this.onKeyDown,
      setHighlightIndex: this.setHighlightIndex
    }, (ref) => { this.dropdownRef = ref; } );
  }
}
