import React, {Component} from 'react'
import classNames from 'classnames/bind'
import {MdCheck} from 'react-icons/lib/md'
import {color} from '../common/constants'
import {array_contains, hash_with_key} from '../common/utilities'
import auto_bind from '../common/auto_bind'
import Button from 'components/utils/button'
import SearchBar from './search_bar'
import Hover from 'components/utils/hover'
import Field from './field'
import {new_values_fuse, action_create_value} from '../common/fields'
import store from '../common/store'
import {alert_failure} from '../actions/display'

let cx = classNames.bind(require('../styles/field.scss'))

class NonExclusiveField extends Component {
  constructor(props) {
    super(props)
    this.state = {
      comment: props.comment,
      active: false,
      query: "",
      results: [],
    }
    auto_bind(this)
  }

  componentDidMount() {
    this.mounted = true
    if (this.should_set_state) {
      this.setState(this.should_set_state)
      this.should_set_state = false
    }
  }

  componentWillUnmount() {
    this.mounted = false
  }

  on_query_change(query, results) {
    if (this.mounted) {
      this.setState({query, results})
    } else {
      this.should_set_state = {query, results}
    }
  }

  create_value() {
    this.search_bar.set_query("")
    this.props.create_value(this.state.query)
    .then((id) => {
      this.props.on_select_value(id)
    }, () => {})
  }

  get_default_results() {
    return this.props.values.sort((a, b) => a.name.localeCompare(b.name)).map((value) => value.id)
  }

  deactivate() {
    this.setState({active: false})
  }

  activate() {
    this.setState({active: true})
    this.focus_search_bar()
  }

  focus_search_bar() {
    setTimeout(() => {
      if (this.mounted && this.search_bar) {
        this.search_bar.focus()
      }
    })
  }

  toggle_selected(selected, value_id) {
    return () => {
      this.should_blur = false
      this.focus_search_bar()
      if (selected) {
        this.props.on_deselect_value(value_id)
      } else {
        this.props.on_select_value(value_id)
      }
    }
  }

  render_hoverable(hover) {
    let editing = this.state.active && this.props.editable
    let use_ellipsis = !hover && !editing
    let {selected_values} = this.props
    if (this.props.ellipsis && use_ellipsis) {
      selected_values = selected_values.slice(0, this.props.ellipsis)
    }
    let values_hash = hash_with_key(this.props.values)
    let displayed_value_ids = this.props.searchable ? this.state.results : this.get_default_results()
    return (
      <div>
        <div
          tabIndex={0}
          onFocus={this.activate}
          className={cx('field__display', {'field__display_empty': this.props.selected_values.length == 0, 'field__display_magnify': hover || editing})}
          >
          {this.props.selected_values.length == 0 ? (
            <div className={cx('field__label', {'field__label_ellipsis': this.props.field_ellipsis})} style={this.props.field_ellipsis ? {maxWidth: this.props.field_ellipsis} : {}}>
              {this.props.placeholder || <span>&hellip;</span>}
            </div>
          ) : (
            selected_values.sort((a, b) => a.name.localeCompare(b.name)).map((value) => (
              <SelectedValue
                key={value.id}
                name={value.name}
                ellipsis={use_ellipsis && this.props.value_ellipsis}
                />
            ))
          )}
          {this.props.ellipsis && selected_values.length < this.props.selected_values.length ? (
            <div style={{...styles.pill, color: color('primary', 'light')}}>&hellip;</div>
          ) : null}
        </div>
        {this.props.editable ? (
          <div className={cx('field__selection-values')} onMouseLeave={this.deactivate}>
            {this.props.searchable ? (
              <SearchBar
                ref={(search_bar) => this.search_bar = search_bar}
                key={'search_bar'}
                className={cx('field__search-bar')}
                make_fuse={new_values_fuse}
                items={this.props.values}
                default_results={this.get_default_results()}
                on_query_change={this.on_query_change}
                placeholder=""
                />
            ) : null}
            <div className={cx('field__selection-values-container')}>
              {displayed_value_ids.length == 0 ? (
                this.props.allow_creating_values && this.state.query.length > 0 ? (
                  <div style={{padding: 5, display: 'flex', justifyContent: 'center', alignItems: 'center'}}>
                    <Button onClick={this.create_value}>
                      Ajouter
                    </Button>
                  </div>
                ) : (
                  <div style={{padding: 10, color: color('black', 'bright'), textAlign: 'center', fontStyle: 'italic', backgroundColor: color('black', 'pale')}}>
                    Aucune valeur
                  </div>
                )
              ) : (
                displayed_value_ids.map((id) => values_hash[id])
                .filter(Boolean)
                .map((value) => {
                  let selected = array_contains(this.props.selected_values, value)
                  return (
                    <SelectionValue
                      key={value.id}
                      name={value.name}
                      selected={selected}
                      on_click={this.toggle_selected(selected, value.id)}
                      />
                  )
                })
              )}
            </div>
          </div>
        ) : null}
      </div>
    )
  }

  render() {
    return (
      <Field
        {...this.props}
        category="non-exclusive"
        className={cx({
          'field_selected-values_empty': this.props.selected_values.length == 0,
          'field_active': this.state.active && this.props.editable
        })}
        >
        <Hover>
          {this.render_hoverable}
        </Hover>
      </Field>
    )
  }
}


class SelectedValue extends Component {
  render() {
    return (
      <div className={cx('field__selected-value', {'field__selected-value_ellipsis': this.props.ellipsis})} style={this.props.ellipsis ? {maxWidth: this.props.ellipsis} : {}}>
        {this.props.name == "" ? (
          <span style={{opacity: 0.54, fontStyle: 'italic'}}>Valeur sans nom</span>
        ) : (
          <span>{this.props.name}</span>
        )}
      </div>
    )
  }
}

class SelectionValue extends Component {
  render() {
    return (
      <div onClick={this.props.on_click} className={cx('field__selection-value', {'field__selection-value_selected': this.props.selected})}>
        {this.props.name == "" ? (
          <span style={{opacity: 0.54, fontStyle: 'italic'}}>Valeur sans nom</span>
        ) : (
          <span>{this.props.name}</span>
        )}
        <span style={{width: 30, textAlign: 'center'}}>
          {this.props.selected ? (
            <MdCheck />
          ) : null}
        </span>
      </div>
    )
  }
}

const styles = {
  pill: {
    borderRadius: 5, paddingLeft: 14, paddingTop: 1, paddingRight: 14, paddingBottom: 1,
  },
  truncate: {
    whiteSpace: "nowrap",
    overflow: "hidden",
    textOverflow: "ellipsis",
  },
}

NonExclusiveField.defaultProps = {
  name: "",
  show_label: true,
  selected_values: [],
  values: [],
  on_select_value: (id) => {},
  on_deselect_value: (id) => {},
  ellipsis: false,
  placeholder: "",
  value_ellipsis: false,
  field_ellipsis: false,
  edit_mode: 'hover',
  editable: true,
  searchable: true,
  allow_creating_values: true,
  create_value: (value) => new Promise((resolve, reject) => reject()),
}

export default NonExclusiveField
