import PropTypes from 'prop-types';
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import TetherComponent from 'react-tether';
import { icons, kinds } from 'Helpers/Props';
import Icon from 'Components/Icon';
import SpinnerIcon from 'Components/SpinnerIcon';
import Link from 'Components/Link/Link';
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
import TextInput from 'Components/Form/TextInput';
import ImportArtistSearchResultConnector from './ImportArtistSearchResultConnector';
import ImportArtistName from './ImportArtistName';
import styles from './ImportArtistSelectArtist.css';

const tetherOptions = {
  skipMoveElement: true,
  constraints: [
    {
      to: 'window',
      attachment: 'together',
      pin: true
    }
  ],
  attachment: 'top center',
  targetAttachment: 'bottom center'
};

class ImportArtistSelectArtist extends Component {

  //
  // Lifecycle

  constructor(props, context) {
    super(props, context);

    this._artistLookupTimeout = null;

    this.state = {
      term: props.id,
      isOpen: false
    };
  }

  //
  // Control

  _setButtonRef = (ref) => {
    this._buttonRef = ref;
  }

  _setContentRef = (ref) => {
    this._contentRef = ref;
  }

  _addListener() {
    window.addEventListener('click', this.onWindowClick);
  }

  _removeListener() {
    window.removeEventListener('click', this.onWindowClick);
  }

  //
  // Listeners

  onWindowClick = (event) => {
    const button = ReactDOM.findDOMNode(this._buttonRef);
    const content = ReactDOM.findDOMNode(this._contentRef);

    if (!button) {
      return;
    }

    if (!button.contains(event.target) && content && !content.contains(event.target) && this.state.isOpen) {
      this.setState({ isOpen: false });
      this._removeListener();
    }
  }

  onPress = () => {
    if (this.state.isOpen) {
      this._removeListener();
    } else {
      this._addListener();
    }

    this.setState({ isOpen: !this.state.isOpen });
  }

  onSearchInputChange = ({ value }) => {
    if (this._artistLookupTimeout) {
      clearTimeout(this._artistLookupTimeout);
    }

    this.setState({ term: value }, () => {
      this._artistLookupTimeout = setTimeout(() => {
        this.props.onSearchInputChange(value);
      }, 200);
    });
  }

  onArtistSelect = (foreignArtistId) => {
    this.setState({ isOpen: false });

    this.props.onArtistSelect(foreignArtistId);
  }

  //
  // Render

  render() {
    const {
      selectedArtist,
      isExistingArtist,
      isFetching,
      isPopulated,
      error,
      items,
      queued
    } = this.props;

    const errorMessage = error &&
      error.responseJSON &&
      error.responseJSON.message;

    return (
      <TetherComponent
        classes={{
          element: styles.tether
        }}
        {...tetherOptions}
      >
        <Link
          ref={this._setButtonRef}
          className={styles.button}
          component="div"
          onPress={this.onPress}
        >
          {
            queued && !isPopulated &&
              <LoadingIndicator
                className={styles.loading}
                size={20}
              />
          }

          {
            isPopulated && selectedArtist && isExistingArtist &&
              <Icon
                className={styles.warningIcon}
                name={icons.WARNING}
                kind={kinds.WARNING}
              />
          }

          {
            isPopulated && selectedArtist &&
              <ImportArtistName
                artistName={selectedArtist.artistName}
                disambiguation={selectedArtist.disambiguation}
                // year={selectedArtist.year}
                isExistingArtist={isExistingArtist}
              />
          }

          {
            isPopulated && !selectedArtist &&
              <div>
                <Icon
                  className={styles.warningIcon}
                  name={icons.WARNING}
                  kind={kinds.WARNING}
                />

                No match found!
              </div>
          }

          {
            !isFetching && !!error &&
              <div>
                <Icon
                  className={styles.warningIcon}
                  title={errorMessage}
                  name={icons.WARNING}
                  kind={kinds.WARNING}
                />

                Search failed, please try again later.
              </div>
          }

          <div className={styles.dropdownArrowContainer}>
            <Icon
              name={icons.CARET_DOWN}
            />
          </div>
        </Link>

        {
          this.state.isOpen &&
            <div
              ref={this._setContentRef}
              className={styles.contentContainer}
            >
              <div className={styles.content}>
                <div className={styles.searchContainer}>
                  <div className={styles.searchIconContainer}>
                    <SpinnerIcon
                      name={icons.SEARCH}
                      isSpinning={isFetching}
                    />
                  </div>

                  <TextInput
                    className={styles.searchInput}
                    name={`${name}_textInput`}
                    value={this.state.term}
                    onChange={this.onSearchInputChange}
                  />
                </div>

                <div className={styles.results}>
                  {
                    items.map((item) => {
                      return (
                        <ImportArtistSearchResultConnector
                          key={item.foreignArtistId}
                          foreignArtistId={item.foreignArtistId}
                          artistName={item.artistName}
                          disambiguation={item.disambiguation}
                          // year={item.year}
                          onPress={this.onArtistSelect}
                        />
                      );
                    })
                  }
                </div>
              </div>
            </div>
        }
      </TetherComponent>
    );
  }
}

ImportArtistSelectArtist.propTypes = {
  id: PropTypes.string.isRequired,
  selectedArtist: PropTypes.object,
  isExistingArtist: PropTypes.bool.isRequired,
  isFetching: PropTypes.bool.isRequired,
  isPopulated: PropTypes.bool.isRequired,
  error: PropTypes.object,
  items: PropTypes.arrayOf(PropTypes.object).isRequired,
  queued: PropTypes.bool.isRequired,
  onSearchInputChange: PropTypes.func.isRequired,
  onArtistSelect: PropTypes.func.isRequired
};

ImportArtistSelectArtist.defaultProps = {
  isFetching: true,
  isPopulated: false,
  items: [],
  queued: true
};

export default ImportArtistSelectArtist;
