import React, {Component} from 'react'
import classNames from 'classnames/bind'
import {MdSearch} from 'react-icons/lib/md'
import styled from 'styled-components'
import {tolerant_equal} from 'selectors/base'
import {cancelable_timeout} from 'common/cancelable'
import {color, input} from 'common/styles'
import auto_bind from 'common/auto_bind'

export default class SearchBar extends Component {
  constructor(props) {
    super(props)
    this.state = {
      query: "",
      results: [],
    }
    auto_bind(this)
    this.fuse = this.props.make_fuse()
  }

  static defaultProps = {
    on_query_change: () => {},
    simple: false,
    extend: true,
    placeholder: "Recherche",
    make_fuse: () => null,
    items: [],
    default_results: [],
    onFocus: () => null,
    onBlur: () => null,
  }

  set_items(items) {
    this.fuse.set(items)
  }

  set_query(query = "") {
    if (this.mounted) {
      this.set_should_verify_results()
      this.setState((state) => ({...state, query}))
    }
  }

  verify_results() {
    const {query} = this.state
    const {default_results, on_query_change} = this.props
    const results = query == "" ? default_results : this.fuse.search(query)
    const results_changed = !tolerant_equal(results, this.previous.results)
    if (!tolerant_equal(query, this.previous.query) || results_changed) {
      if (results_changed) {
        this.setState({results})
      }
      on_query_change(query, results)
    }
  }

  componentDidUpdate() {
    if (this.should_verify_results) {
      this.verify_results()
      this.should_verify_results = false
    }
  }

  componentDidMount() {
    this.mounted = true
    this.set_items(this.props.items)
    this.previous = {query: ''}
    this.verify_results()
  }

  set_should_verify_results() {
    this.previous = {...this.state}
    this.should_verify_results = true
  }

  componentWillReceiveProps(props) {
    const {items, default_results} = this.props
    if (!tolerant_equal(props.items, items)) {
      this.set_items(props.items)
      this.set_should_verify_results()
    }
    if (!tolerant_equal(props.default_results, default_results) && this.state.query == "") {
      this.set_should_verify_results()
    }
  }

  shouldComponentUpdate(props, state) {
    return state !== this.state ||
    !tolerant_equal(props.items, this.props.items) ||
    !tolerant_equal(props.default_results, this.props.default_results) ||
    props.className !== this.props.className ||
    props.placeholder !== this.props.placeholder
  }

  componentWillUnmount() {
    this.mounted = false
  }

  focus() {
    this.input.focus()
  }

  render() {
    const {className} = this.props
    return (
      <Container className={className}>
        <Icon>
          <MdSearch />
        </Icon>
        <Input
          innerRef={(input) => this.input = input}
          type="text"
          placeholder={this.props.placeholder}
          value={this.state.query}
          onChange={({target: {value: query}}) => this.set_query(query)}
          onFocus={(event) => {
            if (this.state.query != "") {
              let input = event.target
              setTimeout(() => input.select(), 100)
            }
            this.props.onFocus()
          }}
          onBlur={this.props.onBlur}
        />
      </Container>
    )
  }
}

const Container = styled.div`
  display: flex;
  align-items: center;
  border-bottom: solid 2px ${color('black', 'pale')};
`
const Icon = styled.div`
  color: ${color('black', 'bright')};
  font-size: 20px;
  padding: 5px;
  flex-shrink: 0;
`
const Input = styled.input`
  ${input}
  flex: 1;
`
