import React from 'react';
import { FormBuilder, Connect, Popover, Input, Icon } from 'amos-framework';
import { getPropsValue } from 'amos-designer';
import imageStatic from '@gm/graphmod-assets';
import SelectModal from './SelectModal';


const BasicForm = FormBuilder.BasicForm;
const enhanceForm = Connect.enhanceForm;
/**
 * 联想输入
 * @class TextInputViewpo
 * @extends {BasicForm}
 */
@enhanceForm
class TextInputViewpo extends BasicForm {

  constructor(props) {
    super(props);
    this.keybordIndex = -1;
    this.state = {
      posVisible: false,
      loaded: false,
      longitude: '',
      latitude: '',
      open: false,
      data: []
    };
  }

  componentDidMount() {
    let _data = getPropsValue(this.props, 'data', {});
    if (_data.actionInit && _data.action) {
      _data.action().then(d => {
        this.setState({
          data: (d || []).map((e, index) => ({
            id: _data.keyName ? e[_data.keyName || 'id'] : index,
            location: e[_data.labelName || 'location'],
            latitude: e[_data.latitudeName || 'latitude'],
            longitude: e[_data.longitudeName || 'longitude']
          }))
        });
      });
    }
  }

  componentWillReceiveProps(nextProps) {
    if (this.props.value !== nextProps.value) {
      this.getValue(nextProps.value || '');
    }
  }

  getValue = (value = '') => {
    const list = typeof (value) === 'string' ? value.split('@address@') : value
    const otherValue = list[1];
    let data = {};
    if (otherValue) {
      data = JSON.parse(otherValue);
    }
    this.setState({ value: list[0], ...data || {} });
  }

  onToggle = (open) => {
    let { width } = this.state;
    if (open) {
      width = this.node.input.clientWidth;
    }
    this.setState({ open, width });
  }

  cancel = () => {
    this.setState({
      posVisible: false
    });
  }

  handLanLonChange = (data) => {
    this.setState({
      ...data
    }, this.onChange);
  }

  handleChange = (value) => {
    let _data = getPropsValue(this.props, 'data.items', []);
    let actionInit = getPropsValue(this.props, 'data.actionInit', false);
    _data = _data.length > 0 ? _data : this.state.data;
    if (value && value.includes('TextInputPoi_')) {
      const _d = _data.find(e => `TextInputPoi_${e.id}` === value) || {};
      this.setState({
        value: _d.location,
        longitude: _d.longitude,
        latitude: _d.latitude
      }, this.onChange);
    } else {
      this.setState({
        value
      }, this.onChange);
    }
    if (getPropsValue(this.props, 'data.items', []).length === 0 && !actionInit) {
      this.requestData(value);
    }
  }

  toggle = () => {
    this.setState(prevState => ({ posVisible: !prevState.posVisible }));
  };

  cancel = () => {
    this.setState({ posVisible: false });
  }

  handLanLonChange = (data) => {
    this.setState({ ...data }, this.onChange);
  }

  onChange = () => {
    const { onChange, url } = this.props;
    const { longitude, latitude, value } = this.state;
    const str = JSON.stringify({ longitude, latitude });
    if (onChange) {
      this.props.onChange(url ? `${value || ''}@address@${str}` : value);
    }
  }

  requestData = (value) => {
    if (this.timeout) {
      clearTimeout(this.timeout);
      this.timeout = null;
    }
    this.currentValue = value;
    const fake = () => {
      const action = this.props.data.action;
      action(value).then(d => {
        if (this.currentValue === value) {
          this.setState({ data: d || [] });
        }
      });
    };
    const long = 300;
    this.timeout = setTimeout(fake, long);
  }

  handleSelect = (d) => () => {
    this.onToggle(false);
    this.handleChange(`TextInputPoi_${d.id}`);
  }

  onBlur = () => {
    if (!this.blur) {
      this.blur = false;
      this.onToggle(false);
    }
  }
  /**
   * 输入框清除
   */
  handleClear = () => {
    this.handleChange('');
  }
  /**
   * 键盘控制下来框选择
   * @param {*} ev
   */
  handleKeyboard = (ev) => {
    if (this.options && this.options.children.length > 0) {
      if (ev.nativeEvent.keyCode === 38) {
        // ↑
        if (this.keybordIndex > 0) {
          this.options.children[this.keybordIndex] && this.options.children[this.keybordIndex].classList.remove('amos-select-option-active');
          this.keybordIndex = this.keybordIndex - 1;
          const optionDom = this.options.children[this.keybordIndex];
          optionDom.classList.add('amos-select-option-active');
          this.options.scrollTop = optionDom.offsetTop - this.options.offsetHeight + optionDom.clientHeight;
        }
      } else if (ev.nativeEvent.keyCode === 40) {
        // ↓
        if (this.keybordIndex < this.options.children.length - 1) {
          this.options.children[this.keybordIndex] && this.options.children[this.keybordIndex].classList.remove('amos-select-option-active');
          this.keybordIndex = this.keybordIndex + 1;
          const optionDom = this.options.children[this.keybordIndex];
          optionDom.classList.add('amos-select-option-active');
          this.options.scrollTop = optionDom.offsetTop - this.options.offsetHeight + optionDom.clientHeight;
        }
      } else if (ev.nativeEvent.keyCode === 13) {
        // enter
        this.options.children[this.keybordIndex] && this.options.children[this.keybordIndex].click();
        this.keybordIndex = -1;
      } else {
        this.options.children[this.keybordIndex] && this.options.children[this.keybordIndex].classList.remove('amos-select-option-active');
        this.keybordIndex = -1;
      }
    } else {
      this.keybordIndex = -1;
    }
  }

  render() {
    const { posVisible, longitude, latitude, value } = this.state;
    const { url } = this.props;
    let _data = getPropsValue(this.props, 'data.items', []);
    _data = _data.length > 0 ? _data : this.state.data;
    const data = _data.filter(e => {
      if ((e.location || '').toLocaleLowerCase().includes((value || '').toLocaleLowerCase())) {
        return true;
      }
      return false;
    });
    return (
      <React.Fragment>
        <div className="gm-common-inputselect-wrapper">
          <Input
            ref={node => this.node = node}
            className="gm-common-inputselect"
            onFocus={() => this.onToggle(true)}
            onBlur={this.onBlur}
            onChange={(e) => this.handleChange(e.target.value)}
            value={value}
            onKeyUp={e => this.handleKeyboard(e)}
          />
          <div className="gm-common-inputselect-icons">
            {value && <Icon icon="cancel" onClick={this.handleClear} />}
            <img onClick={this.toggle} src={longitude && latitude ? imageStatic.common.poiChoice : imageStatic.common.poi} alt="" />
          </div>
          <Popover
            className="gm-common-inputselect-popover-wrapper"
            contentWrapClassName="gm-common-inputselect-popover amos-select-dropdown-popover"
            open={this.state.open}
            onToggle={this.onToggle}
            content={
              <ul
                style={{ width: this.state.width }}
                onMouseOut={() => { this.blur = false; this.node.input.focus(); }}
                onMouseOver={() => this.blur = true}
                ref={node => this.options = node}
                className="amos-select-options"
              >
                {
                  data.map(d => <li className="amos-select-option" key={`TextInputPoi_${d.id}`} onClick={this.handleSelect(d)}>{d.location}</li>)
                }
              </ul>
            }
            direction="down"
            align="left"
            triggerMode="click"
            destroyContent
          >
            <div className="gm-common-inputselect-bar" />
          </Popover>
        </div>
        <SelectModal longitude={longitude} latitude={latitude} onChange={this.handLanLonChange} visible={posVisible} url={url} onCancel={this.cancel} />
      </React.Fragment>
    );
  }
}
TextInputViewpo.propTypes = {};

export default TextInputViewpo;
