import React from 'react'
import R from 'ramda'
import { Tag, Icon } from '@blueprintjs/core'

import Dropdown from '../../Dropdown'
import TextInput from '../TextInput'
import SortableList from '../SortableList'

function Item(props) {
  if (props.isSelected) {
    return (
      <li
        className='o-dropdown-list__item o-dropdown-list__item--selected'
        onClick={props.onClick}>
        <Icon className='o-dropdown-list__item__icon' icon='small-tick' />
        <span className='o-dropdown-list__item__text'>{props.text}</span>
        <Icon className='o-dropdown-list__item__icon' icon='cross' />
      </li>
    )
  } else {
    return (
      <li
        className='o-dropdown-list__item'
        onClick={props.onClick}>
        <span className='o-dropdown-list__item__icon' />
        <span className='o-dropdown-list__item__text'>{props.text}</span>
        <span className='o-dropdown-list__item__icon' />
      </li>
    )
  }
}

class ItemSelectInput extends React.Component {

  constructor(props) {
    super(props)

    this.state = {
      query: ''
    }
  }

  componentDidMount() {
    this.fetchResults()
  }

  handleInputChange(e) {
    e.preventDefault()
    this.setState(
      { query: e.target.value },
      this.fetchResults
    )
  }

  fetchResults() {
    setTimeout(() => this.props.fetchResults(this.state.query), 1)
  }

  addValue(id) {
    if (this.props.many) {
      this.props.onChange(
        R.append(id, this.getSelected()),
        this.props.extraFields
      )
    } else {
      this.props.onChange(id, this.props.extraFields)
    }

    this.closeDropdown()
  }

  removeValue(id) {
    const selected = this.getSelected()
    if (this.props.many) {
      this.props.onChange(
        R.remove(
          R.findIndex(R.equals(id), selected),
          1,
          selected
        ),
        this.props.extraFields
      )
    } else {
      this.props.onChange(null, {})
    }
  }

  clearValues() {
    if (this.props.many) {
      this.props.onChange([], {})
    } else {
      this.props.onChange(null, {})
    }
  }

  openDropdown() {
    this.refs.dropdown.open()
    if (this.state.query === '' || !this.state.query) 
      this.fetchResults()
  }

  closeDropdown() {
    this.refs.dropdown.close()
    this.setState({ query: '' })
  }

  getSelected() {
    if (this.props.many){
      if (this.props.value){
        return typeof this.props.value !== 'object' ? [this.props.value] : this.props.value
      } else {
        return []
      }
    } else {
      return this.props.value ? [this.props.value] : []
    }
  }

  hasSelected() {
    return this.getSelected().length !== 0
  }

  isNotSelected(id) {
    return !R.contains(id, this.getSelected())
  }

  renderNoResults() {
    return (
      <li className='o-dropdown-list__no-results'>No results</li>
    )
  }

  renderDropdown() {
    const selected = this.getSelected()
      .filter(id => this.props.entities[id])
      .map(id => this.props.entities[id])
      .filter(item => item)
      .map(item => (
        <Item
          key={item.id}
          isSelected={true}
          text={item[this.props.attribute]}
          onClick={() => this.removeValue(item.id)} />
      ))

    const results = this.props.results
      .filter(id => this.isNotSelected(id))
      .map(id => this.props.entities[id])
      .map(item => (
        <Item
          key={item.id}
          isSelected={false}
          text={item[this.props.attribute]}
          onClick={() => this.addValue(item.id)} />
      ))
    const createButton = this.props.create ? (
      <button
        className='bp3-button c-input--item-select__search__button'
        onClick={() => this.props.create(this.state.query, data => this.addValue(data.id))}>
        Add
      </button>
    ) : null

    return (
      <div className='c-input--item-select__dropdown'>
        <div className='c-input--item-select__search'>
          <div className='bp3-control-group'>
            <TextInput
              onChange={e => this.handleInputChange(e)}
              value={this.state.query}
              fill={true}
              placeholder='Search' />
            {createButton}
          </div>
        </div>
        <ul className='o-dropdown-list'>
          {selected.length ? selected : null}
          {results.length ? results : this.renderNoResults()}
        </ul>
      </div>
    )
  }

  updateExtraField(id, option) {
    const extraFields = R.assoc(id, option, this.props.extraFields)
    this.props.onChange(this.getSelected(), extraFields)
  }

  renderSortableList() {
    const extraFields = this.props.extraFieldOptions.map(field => (
      <option
        key={field[1]}
        value={field[1]}>{field[0]}</option>
    ))

    const extraFieldsSelect = (item) => (
      <div className='c-input--item-select__item'>
        <div className='c-panel__select'>{item[this.props.attribute]}</div>
        <select
          className='bp3-button c-panel__select__right'
          value={this.props.extraFields[item.id]}
          onChange={e => this.updateExtraField(item.id, e.target.value)}>{extraFields}</select>
      </div>
    )

    const standardSelect = (item) => (
      <div className='c-input--item-select__item'>{item[this.props.attribute]}</div>
    )

    return (
      <SortableList
        items={this.getSelected()}
        entities={this.props.entities}
        onChange={selected => this.props.onChange(selected, this.props.extraFields)}
        renderItem={item =>
          this.props.extraFieldOptions.length ? extraFieldsSelect(item) : standardSelect(item)
        } />
    )
  }

  render() {
    const selected = this.getSelected()

    const Button = (
      <a onClick={() => this.openDropdown()}>
        {this.props.editMessage}
      </a>
    )

    const tagButton = selected.length ? (
      <Tag
        large={true}
        round={true}
        icon={this.props.icon}
        interactive={true}
        onRemove={(e) => {
          this.clearValues()
          e.stopPropagation()
        }}
        onClick={() => this.openDropdown()}>
          {this.props.editMessage}
      </Tag>
    ) : (
      <Tag
        large={true}
        round={true}
        icon={this.props.icon}
        interactive={true}
        onClick={() => this.openDropdown()}>
          {this.props.editMessage}
      </Tag>
    )

    const error = (
      <span className='c-form__input__error bp3-tag bp3-intent-danger'>
        {Array.isArray(this.props.errors) ? this.props.errors.join(' ') : this.props.errors}
      </span>
    )  

    return (
      <div
        className={`c-input c-input--item-select ${this.props.className}`}>
        {this.props.showSortableList ? this.renderSortableList() : null }
        <Dropdown
          ref='dropdown'
          content={this.renderDropdown()}
          inline={this.props.inline}>
          {this.props.tag ? tagButton : Button}
        </Dropdown>
        {this.props.errors && error}
      </div>
    )
  }
}

ItemSelectInput.defaultProps = {
  many: true,
  results: [],
  entities: {},
  extraFields: {},
  extraFieldOptions: [],
  showSortableList: true,
  inline: true
}

export default ItemSelectInput