import React from 'react';
import PropTypes from 'prop-types';

export const ASC = 'ASC';
export const DESC = 'DESC';

const sortingType = PropTypes.shape({
    field: PropTypes.string,
    direction: PropTypes.oneOf([ASC, DESC]).isRequired
});

export const passedWithListPropsTypes = {
    pageSize: PropTypes.number.isRequired,
    activePage: PropTypes.number.isRequired,
    onChangePage: PropTypes.func.isRequired,
    onChangePageSize: PropTypes.func.isRequired,

    fieldsParams: PropTypes.object.isRequired,
    onUpdateFieldParams: PropTypes.func.isRequired,
    onResetFieldParams: PropTypes.func.isRequired,

    filterText: PropTypes.string.isRequired,
    onChangeFilterText: PropTypes.func.isRequired,

    sorting: sortingType,
    onChangeSorting: PropTypes.func.isRequired
};

export const withListProps = Component => {
    return class WithListProps extends React.PureComponent {
        static displayName = `WithListProps(${Component.displayName ||
            Component.name ||
            'Component'})`;

        static propTypes = {
            defaultPageSize: PropTypes.number,
            defaultActivePage: PropTypes.number,
            defaultFilterText: PropTypes.string,
            defaultFieldsParams: PropTypes.object,
            defaultSorting: sortingType
        };

        static defaultProps = {
            defaultPageSize: 10,
            defaultActivePage: 0,
            defaultFilterText: '',
            defaultFieldsParams: {},
            defaultSorting: {
                field: null,
                direction: ASC
            }
        };

        state = {
            pageSize: this.props.defaultPageSize,
            activePage: this.props.defaultActivePage,
            filterText: this.props.defaultFilterText,
            fieldsParams: this.props.defaultFieldsParams,
            sorting: this.props.defaultSorting
        };

        getPaginationProps() {
            const {pageSize, activePage} = this.state;

            return {
                pageSize,
                activePage,
                onChangePage: activePage => {
                    this.setState({activePage});
                },
                onChangePageSize: pageSize => {
                    this.setState({pageSize, activePage: 0});
                }
            };
        }

        handleUpdateFieldParams = ({field, params}) => {
            const fieldsParams = {...this.state.fieldsParams};
            fieldsParams[field] = params;

            this.setState({fieldsParams, activePage: 0});
        };

        handleResetFieldParams = field => {
            const fieldsParams = {...this.state.fieldsParams};
            delete fieldsParams[field];

            this.setState({fieldsParams, activePage: 0});
        };

        getFieldsParamsProps() {
            const {fieldsParams} = this.state;

            return {
                fieldsParams,
                onUpdateFieldParams: this.handleUpdateFieldParams,
                onResetFieldParams: this.handleResetFieldParams
            };
        }

        getFilterTextProps() {
            const {filterText} = this.state;

            return {
                filterText,
                onChangeFilterText: filterText => {
                    this.setState({filterText, activePage: 0});
                }
            };
        }

        handleChangeSorting = (field, direction) => {
            const sorting = {field, direction};

            this.setState({sorting});
        };

        getSortingProps() {
            const {sorting} = this.state;

            return {
                sorting,
                onChangeSorting: this.handleChangeSorting
            };
        }

        getListProps = () => {
            return {
                ...this.getFilterTextProps(),
                ...this.getPaginationProps(),
                ...this.getFieldsParamsProps(),
                ...this.getSortingProps()
            };
        };

        render() {
            return <Component {...this.getListProps()} {...this.props} />;
        }
    };
};
