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

import {PurePagination} from '../PurePagination';

export class Pagination extends React.Component {
    static PagingModes = PurePagination.PagingModes;

    static propTypes = {
        store: PropTypes.object.isRequired,
        availablePageSizes: PropTypes.array,
        defaultPageSize: PropTypes.number,
        beforeNavigate: PropTypes.func,
        beforeDropdownChange: PropTypes.func,
        onPageSizeChange: PropTypes.func,
        onPageChange: PropTypes.func
    };

    static defaultProps = {
        availablePageSizes: [10, 25, 50, 100, 500],
        defaultPageSize: 25,
        beforeNavigate: null,
        beforeDropdownChange: null,
        onPageSizeChange: null,
        onPageChange: null
    };

    constructor(props) {
        super(props);

        this.store = this.props.store;

        this.state = this.getOriginalState();

        this.onStoreChange = () => {
            if (this.unmounted) {
                return;
            }
            this.setState({
                itemsCount: this.store.getFilteredCount(),
                activePage: this.store.getCurrentPage(),
                pageSize: this.store.getPageSize()
            });
        };
    }

    componentWillMount() {
        this.store.on('change', this.onStoreChange, this);
    }

    componentWillReceiveProps(nextProps) {
        this.store.off('change', this.onStoreChange);
        this.store = nextProps.store;
        this.setState(this.getOriginalState());
        this.store.on('change', this.onStoreChange, this);
    }

    componentWillUnmount() {
        this.unmounted = true;
        this.store.off('change', this.onStoreChange);
    }

    getOriginalState() {
        let isPageSizeCollision = !_.includes(
            this.props.availablePageSizes,
            this.store.getPageSize()
        );

        let pageSize = isPageSizeCollision ? this.props.defaultPageSize : this.store.getPageSize();

        if (isPageSizeCollision) {
            this.store.setPageSize(this.props.defaultPageSize);
        }

        return {
            itemsCount: this.store.getFilteredCount(),
            activePage: this.store.getCurrentPage(),
            pageSize: pageSize
        };
    }

    navigate(page) {
        const {beforeNavigate} = this.props;

        if (typeof beforeNavigate === 'function') {
            beforeNavigate(this.handleNavigate.bind(this, page));
        } else {
            this.handleNavigate(page);
        }
    }

    dropdownChange({value: pageSize, selectedIndex}) {
        const {onPageSizeChange, onPageChange} = this.props;

        let actualIndex = selectedIndex;

        let prevActivePage = this.state.activePage;
        let nextActivePage = 0;
        this.setState({
            pageSize,
            activePage: nextActivePage
        });

        this.store.setPageSize(pageSize);

        if (typeof onPageSizeChange === 'function') {
            onPageSizeChange(pageSize, actualIndex);
        }

        if (prevActivePage !== nextActivePage && typeof onPageChange === 'function') {
            onPageChange(nextActivePage);
        }
    }

    handleNavigate(activePage) {
        const {onPageChange} = this.props;

        this.setState({activePage});
        this.store.setCurrentPage(activePage);

        if (typeof onPageChange === 'function') {
            onPageChange(activePage);
        }
    }

    handleChangePageSize = (value, selectedIndex) => {
        const eventData = {value, selectedIndex};

        if (typeof this.props.beforeDropdownChange === 'function') {
            this.props.beforeDropdownChange(this.dropdownChange.bind(this, eventData));
        } else {
            this.dropdownChange(eventData);
        }
    };

    handleChangePage = page => {
        this.navigate(page);
    };

    render() {
        return (
            <PurePagination
                {...this.props}
                activePage={this.state.activePage}
                itemsCount={this.state.itemsCount}
                pageSize={this.state.pageSize}
                pageSizes={this.props.availablePageSizes}
                onChangePage={this.handleChangePage}
                onChangePageSize={this.handleChangePageSize}
            />
        );
    }
}
