import React from 'react';
import { Dropdown, Menu, Empty, Spin, Icon, Input } from 'antd';
import { findDOMNode } from 'react-dom';
import lodash from 'lodash';
import styles from './styles.less';

/*
 * 此空间用于数据选择及输入控制,若不选择只传入输入框数据
 */

class TextSelect extends React.Component {
    input: any;
    constructor(props) {
        super(props);
        this.state = {
            searchStr: '',
            list: [],
            loading: false,
            selected: undefined,
            tempSelected: undefined,
            tempVisible: false,
        };
        this._fetch = lodash.debounce(this._fetch, 400);
    }

    inputWidth: number = 320;

    static getDerivedStateFromProps(nextProps, prevState) {
        if (JSON.stringify(nextProps.value) !== JSON.stringify(prevState.tempSelected)) {
            let searchStr =
                nextProps.value && nextProps.value[0] ? nextProps.value[0].label || nextProps.value[0].text : '';
            return {
                tempSelected: nextProps.value || [],
                selected: nextProps.value,
                searchStr,
            };
        }
        return null;
    }

    componentDidMount() {
        setTimeout(this.getInputWidth, 10);
    }

    getInputWidth = () => {
        if (this.input && findDOMNode(this.input)) {
            this.width = findDOMNode(this.input).offsetWidth;
        }
    };
    _fetch = async (val) => {
        const request = this.props.request;
        if (!request) return;
        await this.setState({ loading: true, list: [] });
        const result = await request(val);
        if (result && result.success) {
            const data = result.data || {};
            let list = Array.isArray(data.list) ? data.list : [];
            list = this.formateData(list);
            this.setState({ list });
        }
        await this.setState({ loading: false });
    };
    formateData = (data) => {
        const { fieldNames = { label: 'name', value: 'id' } } = this.props || {};
        return data.map((item) => ({
            ...item,
            _label: item[fieldNames.label],
            _value: item[fieldNames.value],
        }));
    };
    onResetValue = (searchStr) => {
        return { value: '', label: searchStr };
    };
    onSearch = (e) => {
        const searchStr = e.currentTarget.value;
        const selected = this.onResetValue(searchStr);
        this.setState({ searchStr, selected }, () => {
            this._fetch(searchStr);
            this.onChange(selected);
        });
    };
    onFocus = () => {
        this._fetch(this.state.searchStr);
    };
    onClickMenu = ({ item, key }) => {
        const { props } = item || {};
        const { title } = props || {};
        const selected = { label: title, value: key };
        this.setState({ selected, searchStr: title });
        this.onVisibleChange(false);
        this.onChange(selected);
    };
    onChange = (obj) => {
        this.props.onChange && this.props.onChange(obj);
    };
    onClear = () => {
        const { tempVisible } = this.state;
        const searchStr = '';
        const selected = this.onResetValue(searchStr);
        this.setState({ searchStr, selected }, () => {
            tempVisible && this._fetch(searchStr);
            this.onChange(selected);
        });
    };
    onVisibleChange = (tempVisible) => {
        this.setState({ tempVisible });
    };
    renderList = () => {
        const { list, loading, selected } = this.state;
        return (
            <Menu
                style={{ width: this.props.width || this.width }}
                onClick={this.onClickMenu}
                selectedKeys={selected ? [selected.value] : []}
            >
                {list.map((item) => (
                    <Menu.Item key={item._value} title={item._label}>
                        {item._label}
                    </Menu.Item>
                ))}
                {loading ? (
                    <Menu.Item>
                        <span className={styles.spin}>
                            <Spin />
                        </span>
                    </Menu.Item>
                ) : null}
                {list.length === 0 ? (
                    <Menu.Item>
                        <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
                    </Menu.Item>
                ) : null}
            </Menu>
        );
    };
    renderSuffix = () => {
        if (this.props.suffix) return this.props.suffix;
        const { searchStr } = this.state;
        const { allowClear = true } = this.props;
        return (
            <>
                <span className={styles.searchIcon}>
                    {' '}
                    <Icon type="search" />
                </span>
                {searchStr.length > 0 && allowClear ? (
                    <span className={styles.clearIcon} onClick={this.onClear}>
                        {' '}
                        <Icon
                            type="close-circle"
                            theme="filled"
                            style={{
                                fontSize: '14px',
                                color: 'rgba(0,0,0,.25)',
                            }}
                        />
                    </span>
                ) : null}
            </>
        );
    };

    render() {
        const { placeholder } = this.props;
        return (
            <Dropdown
                trigger={['click']}
                overlayClassName={styles.overlayClassName}
                overlayStyle={{ maxHeight: 400, overflow: 'auto', marginTop: '7px' }}
                onVisibleChange={this.onVisibleChange}
                placement={'bottomCenter'}
                overlay={this.renderList()}
            >
                <Input
                    ref={(dom) => (this.input = dom)}
                    className={styles.input}
                    value={this.state.searchStr}
                    placeholder={placeholder}
                    onChange={this.onSearch}
                    onFocus={this.onFocus}
                    suffix={this.renderSuffix()}
                />
            </Dropdown>
        );
    }
}

export default TextSelect;
