import Select from 'react-select'
import React from 'react';
import PropTypes from 'prop-types'
import Styles from './styles'
import { WarningWrapper } from '../StyledWrappers';
import { debounce } from '../../../UtilitiesFunctions/objectUtilities';
import Button from '../Button'
import { Row, Column } from '../../baseComponents'
import OtherDropDown from './OtherDropDown'

export class DropDown extends React.Component {

  static get propTypes() {
    return {
      items: React.PropTypes.array.isRequired,
      multiple: React.PropTypes.bool,
      disabled: React.PropTypes.bool,
      clearable: React.PropTypes.bool,
      placeholder: React.PropTypes.string,
      loading: React.PropTypes.bool,
      onChange: React.PropTypes.func.isRequired,
      value: React.PropTypes.array,
      showWarning: React.PropTypes.bool,
      warningClassName: React.PropTypes.string,
      label: React.PropTypes.string,
      isRequired: React.PropTypes.bool,
      setDefaultItem: React.PropTypes.bool,
      serverSideSearch: React.PropTypes.bool
    };
  }


  constructor(props) {
    super(props)
    this.state = {
      warning: '',
      selected: props.value || [],
      defaultSet: false,
      implicitlyChanged: false
    }

  }

  componentDidMount() {
    this.setState({ 'defaultSet': false });
    if (this.props.fetchItems) {
      this.props.fetchItems('');
    }
    if (this.props.setDefaultItem && this.props.items.length == 1) {
      if (!this.state.defaultSet) {
        this.setState({ selected: [this.props.items[0]] })
        this.props.onChange([this.props.items[0]])
        this.setState({ 'defaultSet': true })
      }
    }
  }

  componentWillReceiveProps(np) {
    // For setting the value in case of just one value in the dropdown
    if (np.setDefaultItem && np.items.length == 1) {
      if (this.props.items.length == np.items.length && this.props.items.length == 1 && JSON.stringify(this.props.items) != JSON.stringify(np.items)) {
        this.setState({ selected: [np.items[0]] })
        np.onChange([np.items[0]])
        this.setState({ 'defaultSet': true })
      }
      else if (!this.state.defaultSet) {
        this.setState({ selected: [np.items[0]] })
        np.onChange([np.items[0]])
        this.setState({ 'defaultSet': true })
      }
    }
    var oldValue = (this.props.value && this.props.value.length && this.props.value[0].hasOwnProperty('value')) ? this.props.value[0]['value'] : '';
    var newValue = (np.value && np.value.length && np.value[0].hasOwnProperty('value')) ? np.value[0]['value'] : '';
    // console.log('oldValue: ',oldValue);
    // console.log('newValue: ',newValue);
    if (oldValue == 'CLEAR_COMMAND' && newValue == 'CLEAR_COMMAND') {
      this.setState({ selected: [] })
    }
    if (oldValue != newValue) {
      if (this.state.implicitlyChanged) {
        this.setState({ 'implicitlyChanged': false });
      }
      else {
        var val = np.value && np.value.length && np.value[0].hasOwnProperty('value') ? np.value : []
        np.onChange(val)
        this.setState({ selected: val })
      }
    }

    // For remounting in case the data(items) are equal in length but there content is different
    if (np.setDefaultItem && this.props.items.length == np.items.length && JSON.stringify(this.props.items) != JSON.stringify(np.items)) {
      this.setState({ selected: [np.items[0]] });
      np.onChange([np.items[0]]);
    }
  }

  validate = () => {
      if(this.props.isRequired && !(this.state.selected && this.state.selected.length)){
        this.setState({warning: 'Please select a value'})
        return false
      }
      return true
}

  onChange = selected => {
    var _selected = this.props.multiple ? selected : (selected ? [selected] : [])
    this.setState({ 'implicitlyChanged': true });
    this.props.onChange(_selected)
    this.setState({ selected: _selected, warning: '' })
  }

  onInputChange = debounce((searchValue) => {
    if (searchValue != this.searchValue && this.props.serverSideSearch && this.props.fetchItems) {
      this.searchValue = searchValue
      this.props.fetchItems(searchValue)
    }
  }, 300)


  render() {
    var {
      items,
      multiple,
      disabled,
      clearable,
      placeholder,
      loading,
      onChange,
      value,
      showWarning,
      warningClassName,
      label,
      isRequired,
      setDefaultItem,
      serverSideSearch,
      className
    } = this.props

    const _disabled = () => {
      if (disabled || (setDefaultItem && items.length == 1)) {
        return true;
      }
      return false
    }

    const _warning = this.state.warning && showWarning && <WarningWrapper className={warningClassName}>{this.state.warning}</WarningWrapper>

    const _placeholder = <span title={placeholder || ''}>{placeholder || ''}</span>

    const _label = label && <span className="label">{`${label}${isRequired ? ' *' : ''}`}</span>

    const _value = multiple ? this.state.selected : this.state.selected[0]

    const _title = multiple ?
      this.state.selected.reduce((acc, cur) => acc + ', ' + cur.label || '', '').substr(1) :
      this.state.selected[0] && this.state.selected[0].label || ''

    const valueRenderer = option => <div id='dd-value' className='ddValue' title={_title}>{option.label}</div>

    return (
      <Styles className={`ddWrap ${this.props.WrapperclassName}`}>
        {_label}
        <div className={`${this.state.warning ? 'show-error' : ''} ${this.props.inputWrapperClassName}`}>
          <Select
            {...this.props}
            valueRenderer={valueRenderer}
            options={items}
            multi={multiple}
            disabled={_disabled()}
            clearable={clearable}
            placeholder={_placeholder}
            isLoading={loading}
            onChange={this.onChange}
            value={_value}
            closeOnSelect={!multiple}
            onInputChange={this.onInputChange}
            openOnFocus={true}
          />
        </div>
        {_warning}
      </Styles>
    )
  }

  componentDidUpdate() {
    var el = document.getElementById('dd-value')
    if (el) {
      el.ondblclick = function () {
        event.preventDefault();
        var sel = window.getSelection();
        var range = document.createRange();
        range.selectNodeContents(this);
        sel.removeAllRanges();
        sel.addRange(range);
      }
    }
  }
}

export const AddNewButtonDropDown = props => (
  <DropDown
    noResultsText={<Column center>
      <Row center style={{ 'font-style': 'italic' }}>No Results Found</Row>
      <Button
        style={{ width: '100%' }}
        label={props.addNewButtonLabel}
        buttonType='label'
        themeType='prime-panel-primary'
        onClick={props.addNewButtonOnClick}
      /></Column>}
    {...props}
  />
)

export const OtherDropDownApp = props => (
  <OtherDropDown
    {...props}
  />
)