import React from 'react';
import PropTypes from 'prop-types';
import { createNamespace } from '../../tools/namingTools';
import { generateUniqueID } from '../../tools/helpers';
import { handlePageSelect } from '../../tools/paginationHelper';
import { TYPE_PREVIOUS, TYPE_ELLIPSIS, TYPE_PAGE, STATUS_DISABLED, STATUS_SELECTED } from '../../constants/components/paging';
import { paginationPropTypes } from '../../constants/prop-types/listingProducts/pagination';
import { productListDataStore } from '../../store/productListData';
import Icon from '../icon/Icon';
import './styles/Paging.scss';

const n = createNamespace('Paging');

const Paging = ({
    data: {
        pagesList,
        i18n: i18nProp
    },
    size
}) => {
    if (!pagesList || !pagesList.length) {
        return null;
    }

    // divide pages in 3 groups, to wrap them: before ellipsis, ellipsis and after ellipsis
    const ellipsisIndex = pagesList.findIndex(page => page.type === TYPE_ELLIPSIS);

    const pagingGroupList = ellipsisIndex !== -1 && [
        [...pagesList.slice(0, ellipsisIndex)],
        [...pagesList.slice(ellipsisIndex, ellipsisIndex + 1)],
        [...pagesList.slice(ellipsisIndex + 1)]
    ];

    const i18n = { ...Paging.defaultProps.data.i18n, ...i18nProp };

    const { listingPage, setListingPage, listingLastPage } = productListDataStore();

    const renderLink = (content, linkProps, modifiers, value, isPage = false, isCurrentPage = false, pageType) => {
        const isButtonDisabled = modifiers.includes(STATUS_DISABLED);
        let ariaLabel;
        if (isPage && isCurrentPage) {
            ariaLabel = `${i18n.currentPage}, ${i18n.page.toLowerCase()} ${content}`;
        } else if (isPage) {
            ariaLabel = `${i18n.goToPage} ${content}`;
        } else {
            ariaLabel = pageType === TYPE_PREVIOUS ? i18n.previous : i18n.next;
        }

        return (
            <a
                {...n('page', modifiers).withTestId().props}
                {...linkProps}
                onClick={e => (
                    isButtonDisabled
                        ? () => {}
                        : handlePageSelect(e, value, listingPage, setListingPage, listingLastPage)
                )}
                onKeyDown={() => {}}
                aria-disabled={isButtonDisabled}
                aria-label={ariaLabel}
                aria-current={isCurrentPage ? 'page' : undefined}
            >
                {content}
            </a>
        );
    };

    const getArrowContent = type => (
        <Icon {...n('arrowIcon').withTestId().props} type={type === TYPE_PREVIOUS ? 'caretLeft' : 'caretRight'} />
    );

    const renderPage = page => {
        const { type: pageType, status: pageStatus, url: pageUrl, nb: pageNb } = page;

        switch (pageType) {
            case TYPE_ELLIPSIS:
                return '...';
            default: {
                const isDisabled = pageStatus && pageStatus === STATUS_DISABLED;
                const isCurrentPage = pageStatus && pageStatus === STATUS_SELECTED;

                const isPage = pageType === TYPE_PAGE;
                const content = isPage ? pageNb : getArrowContent(pageType);
                const value = isPage ? pageNb : pageType;
                const props = {};
                if (pageUrl && !isDisabled) {
                    Object.assign(props, { href: pageUrl });
                } else if (isDisabled) {
                    props.href = '#';
                }
                const selectedPageModifier = isCurrentPage ? 'current' : '';
                const disabledPageModifier = isDisabled ? STATUS_DISABLED : '';
                const modifiers = [selectedPageModifier, disabledPageModifier];

                return renderLink(content, props, modifiers, value, isPage, isCurrentPage, pageType);
            }
        }
    };

    const renderPageItem = (page, index, pageGroupList) => {
        const { type: pageType } = page;
        const modifiers = pageType === TYPE_ELLIPSIS ? [
            'ellipsis'
        ] : [
            index === 0 && 'first',
            pageGroupList.length - 1 === index && 'last'
        ];

        return (
            <li
                {...n('item', modifiers).props}
                key={generateUniqueID([page.type, page.nb])}
            >
                {renderPage(page)}
            </li>
        );
    };

    const renderPageGroup = pageGroupList => {
        if (!pageGroupList || !pageGroupList.length) {
            return null;
        }

        return pageGroupList.map(renderPageItem);
    };

    return (
        <nav {...n('wrapper', size).props} aria-label={i18n.title}>
            <ul {...n('list').props}>
                {pagingGroupList && pagingGroupList.length ? (
                    pagingGroupList.map(renderPageGroup)
                ) : (
                    pagesList.map(renderPageItem)
                )}
            </ul>
        </nav>
    );
};

Paging.propTypes = {
    data: PropTypes.shape(paginationPropTypes),
    size: PropTypes.oneOf(['small'])
};

Paging.defaultProps = {
    data: {
        nbPages: 0,
        start: 0,
        simplePagesList: '',
        pagesList: [],
        i18n: {
            previous: 'Previous Page',
            next: 'Next Page',
            title: 'Pagination',
            page: 'Page',
            goToPage: 'Go to page',
            currentPage: 'Current page'
        }
    },
    size: null
};

export default Paging;
