import * as React from 'react';
import {BasicConfig, BasicContainer, BasicContainerPropsInterface} from '../../render/core/Container/types';
import componentLoader from '../../render/util/componentLoader';
import {AutoComplete} from '@native-ads/antd';
import {isPlainObject, debounce} from 'lodash';
import {compileExpressionString, isExpression} from '../../render/util/vm';
import {request} from '../../render/services/api';
import {parseExpressString} from '../../render/parser/index';

export interface RemoteConfig {
    /**
     * 请求地址
     */
    url: string;
    /**
     * 请求方法
     */
    method: string;

    /**
     * 请求数据
     */
    data: Object;

    /**
     * 映射接口值到dataSource
     */
    retMapping: string;
}

export class AutoCompleteConfig extends BasicConfig {
    /**
     * 数据模型Key
     */
    name: string;

    /**
     * 初始化的默认值
     */
    defaultValue: string;

    /**
     * 下拉数据源
     */
    dataSource: string[];

    /**
     * 动态加载数据配置
     */
    loadDataConfig?: RemoteConfig;
}

export class AutoCompletePropsInterface extends BasicContainerPropsInterface {
    info: AutoCompleteConfig;
}

export interface AutoCompleteStateInterface {
    dataSource: string[];
}

export class AbstractAutoComplete extends BasicContainer<AutoCompletePropsInterface, AutoCompleteStateInterface> {
    constructor(props: AutoCompletePropsInterface) {
        super(props);

        this.state = {
            dataSource: []
        };

        this.handleSearch = this.handleSearch.bind(this);
        this.requestData = debounce(this.requestData.bind(this), 300, { 'trailing': true });
    }

    componentWillMount() {
        if (this.props.$setData && this.props.info.defaultValue) {
            const $setData = this.props.$setData;
            $setData(this.props.info.name, this.props.info.defaultValue);
        }
    }

    private handleSearch(value: string) {
        let info = this.props.info;

        if (info.loadDataConfig) {
            this.requestData(value, info.loadDataConfig);
        } else {
            console.info('如果你想通过输入动态请求数据，那么请使用loadDataConfig属性');
        }
    }

    private requestData(searchValue: string, config: RemoteConfig) {
        if (!isPlainObject(config)) {
            console.error('loadDataConfig 属性必须是一个纯对象');
        }

        let runTime = this.getRuntimeContext();
        let sendData = compileExpressionString(config.data, {
            ...runTime,
            $args: {
                search: searchValue
            }
        });

        request(config.url, {
            url: config.url,
            method: config.method,
            data: sendData
        }).then(response => {
            let data = response.data;
            let source: string[];
            if (isExpression(config.retMapping)) {
                source = parseExpressString(config.retMapping, {
                    ...runTime,
                    $output: data
                });
            } else {
                source = data;
            }

            this.setState({
                dataSource: source
            });
        });
    }

    render() {
        let info = this.getPropsInfo(this.props.info);

        if (!info.name) {
            return this.errorReport('name property is required for autoComplete component', 'div');
        }

        if (!this.isUnderContainerEnv()) {
            return this.errorReport('autoComplete component should be under container component control', 'div');
        }

        let dataSource;

        if (info.loadDataConfig) {
            dataSource = this.state.dataSource;
        } else {
            dataSource = info.dataSource;
        }

        return (
            <AutoComplete
                style={this.props.info.style}
                className={this.props.info.className}
                dataSource={dataSource}
                onSelect={val => {
                    if (this.props.$setData) {
                        this.props.$setData(info.name, val);
                    }
                    this.commonEventHandler('onSelect', {
                        value: val
                    });
                }}
                onSearch={this.handleSearch}
            />
        );
    }
}

componentLoader.addComponent('autoComplete', AbstractAutoComplete, AutoCompletePropsInterface);
