import React, { useState, useRef, ReactElement, useEffect } from 'react';
import { Button, Row, Col } from 'antd';
import { Input as AntdInput, InputNumber as AntdInputNumber } from 'antd';
import classNames from 'classnames';
import { InputProps } from 'antd/lib/input';
import { InputState } from 'antd/lib/input/Input';
import { InputNumberProps } from 'antd/lib/input-number';

export type FilterType = {
    title?: string,
    label?: string,
    elem?: React.ReactElement,
    render?: React.ReactElement,
    [propName: string]: any,
    spanMultiple?: number,  // 暂不支持，间距没有适配
}

const Filter:React.FunctionComponent<{label:string}> = (props) => {
    return (
        <>
            {props.label ? <span className={"filter-title"}>
                { props.label }
            </span> : null}
            {props.children ? <span className={"filter-item"} >
                { props.children }
            </span> : null}
        </>
    )
}

const Arrow:React.FunctionComponent<{onClick?:() => void, isDown:boolean, style?:React.CSSProperties}> =
    ({onClick, isDown, style}) => {
        return (
            <span className={"jad-page-layout1-arrow-container"}>
                <i
                    className={`${isDown ? "down": "up"} ${"arrow"}`}
                    style={style}
                    onClick={() => {
                        onClick && onClick();
                    }}
                >
                </i>
            </span>
        )
    }

const FoldButton:React.FunctionComponent<{isFold: boolean, onClick:Function, style?:any}> = ({isFold, onClick, style}) => {
    return (
        <button
            onClick={() => {
                onClick();
            }}
            className={'jad-page-layout1-fold-button'}
            style={{
                position: 'absolute',
                left: '50%',
                top: '50%',
                transform: 'translate(-50%, -50%)',
                ...style,
            }}
        >
            <span
                style={{ marginRight: '6px', }}
            >
                { isFold ? '展开' : '收起' }
            </span>
            <Arrow isDown={isFold}></Arrow>
        </button>
    )
}

/* PageFilterContext: 用于存储 PageFilter 下的 onSearch */
const PageFilterContext = React.createContext(null);

class Input extends React.Component<InputProps, InputState> {
    static contextType = PageFilterContext;
    static Group = AntdInput.Group;
    render() {
        const onSearch = (this.context && typeof this.context === 'function') ? this.context : null;
        return (
            <>
                <AntdInput
                    onPressEnter={() => (onSearch && onSearch())}
                    {...this.props}>
                </AntdInput>
            </>
        );
    }
}

class InputNumber extends React.Component<InputNumberProps> {
    static contextType = PageFilterContext;
    static Group = AntdInput.Group;
    render() {
        const onSearch = (this.context && typeof this.context === 'function') ? this.context : null;
        return (
            <>
                <AntdInputNumber
                    style={{ width: '100%' }}
                    onPressEnter={() => (onSearch && onSearch())}
                    {...this.props}>
                </AntdInputNumber>
            </>
        );
    }
}

type PageFiltersProps = {
    filters: (FilterType|React.ReactElement)[],
    onResetFilters?: () => void,
    onSearch?: () => void | Promise<void>,
    className?: string,
    loading?:boolean,
    [propName: string]: any,
}

const ANTD_GRID = 24;
const EVERY_WIDTH = 310+24; // width + paddingRight

interface StaticComponents {
    Input: typeof Input,
    InputNumber: typeof InputNumber,
}

const PageFilter:React.FunctionComponent<PageFiltersProps> & StaticComponents = ({
    filters,
    onResetFilters,
    onSearch,
    className,
    loading: propsLoading,
    ...rest
}) => {
    const [ isFold, setIsFold ] = useState(true);
    const [ loading, setLoading ] = useState(propsLoading || false);
    const [ colCnt, setColCnt ] = useState(3);
    const showLoading = typeof propsLoading == 'boolean' ? propsLoading : loading;
    const averageCol = ANTD_GRID / colCnt;
    const isLastCol = (index) => (index % colCnt === colCnt - 1);    
    const container = useRef(null);

    useEffect(() => {
        function handleResize() {
            const colCnt = Math.floor(container.current.offsetWidth / EVERY_WIDTH);
            setColCnt(Math.min(4, colCnt));
        }
        handleResize();
        window.addEventListener('resize', handleResize);
        return () => window.removeEventListener('resize', handleResize);
    }, []);

    const needFoldButton = filters.length + 1 > colCnt;
    const filtersShow = isFold ? filters.slice(0, colCnt-1) : filters;  // 1 is left for search button
    const filtersLength = filtersShow.length;

    return (
            <PageFilterContext.Provider value={ onSearch }>
                <div
                    ref={container}
                    className={classNames('jad-page-layout1-filter-board', className)}
                    {...rest}>
                    <Row style={{width: '100%'}}>
                        {
                            (filtersShow)
                                .map((filter, index) => {
                                    const { title, label, elem, render } = filter as FilterType;
                                    const renderFilter = title == null && label == null && elem == null && render == null ? (filter as ReactElement) : null; // 如果 filter 直接传入为 ReactElement
                                    const getSelectStyle:any = (index) => ({
                                        paddingRight: isLastCol(index) ? '0' : '24px',
                                    });
                                    return (
                                        <Col span={averageCol} key={index}>
                                            <div className={"select"} style={ getSelectStyle(index) }>
                                                {
                                                    renderFilter ? renderFilter : (
                                                        <>
                                                            {(title || label) ? <span className={"filter-title"}>
                                                                { title || label }
                                                            </span> : null}
                                                            {elem || render ? <span className={"filter-item"} >
                                                                { elem || render }
                                                            </span> : null}
                                                        </>
                                                    )
                                                }
                                            </div>
                                        </Col>
                                    )
                                })
                        }
                        {
                            (onResetFilters || onSearch) && <Col className={"buttons"}
                                span={(colCnt - (isFold ? filtersShow.length : (filtersLength % colCnt))) * averageCol}>
                                {
                                    onResetFilters && (
                                        <Button
                                            disabled={showLoading}
                                            style={{ float: 'right', marginRight: '10px', }}
                                            onClick={ onResetFilters }>
                                            重置
                                        </Button>
                                    )
                                }
                                {
                                    onSearch && (
                                        <Button
                                            loading={showLoading}
                                            style={{ float: 'right', }}
                                            type="primary"
                                            onClick={ async () => {
                                                setLoading(true);
                                                await onSearch()
                                                setLoading(false);
                                            }}>
                                            查询
                                        </Button>
                                    )
                                }
                            </Col>
                        }
                        {
                            needFoldButton && (
                                <Col className={"jad-page-layout1-fold-button-col"} span={ANTD_GRID}>
                                    <FoldButton
                                        onClick={() => { setIsFold(!isFold); }}
                                        isFold={isFold}>
                                    </FoldButton>
                                </Col>
                            )
                        }
                    </Row>
                </div>
            </PageFilterContext.Provider>
    )
}

PageFilter.Input = Input
PageFilter.InputNumber = InputNumber

export {
    PageFilter,
    Filter,
    Arrow,
}
