import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { createNamespace } from '../../tools/namingTools';
import { normalizeString } from '../../tools/stringTools';
import { KEY_CODE, KEY_VALUE } from '../../constants/keyCodes';
import Icon from '../icon/Icon';
import './styles/ContentDropdown.scss';

const n = createNamespace('ContentDropdown');
const ContentDropdown = ({
    label,
    items,
    selectedItemId,
    onClickItemCallback,
    closeOnItemClick,
    selectedItemContentOverride,
    initiallyOpen
}) => {
    const [isDropdownOpen, setDropdownOpen] = useState(initiallyOpen);
    const [itemsTabIndex, setItemsTabIndex] = useState(initiallyOpen ? 0 : -1);

    useEffect(() => {
        setItemsTabIndex(isDropdownOpen ? 0 : -1);
    }, [isDropdownOpen]);

    const toggleDropdown = () => {
        setDropdownOpen(!isDropdownOpen);
    };

    const handleItemClick = (itemId, isDisabled) => {
        if (isDisabled) { return; }
        onClickItemCallback(itemId);
        if (closeOnItemClick) {
            setDropdownOpen(false);
        }
    };

    const enterHasBeenPressed = e => (e.key === KEY_VALUE.return || e.which === KEY_CODE.return);

    const handleItemKeyDown = (e, itemId, isDisabled) => {
        if (enterHasBeenPressed(e)) {
            handleItemClick(itemId, isDisabled);
        }
    };

    const handleLabelKeyDown = e => {
        if (enterHasBeenPressed(e)) {
            toggleDropdown();
        }
    };

    const modifiers = isDropdownOpen ? ['open'] : ['closed'];
    const labelId = `content-dropdown-${normalizeString(label)}`;
    const renderList = () => (
        <div {...n('list', modifiers).withTestId().props} role="listbox" aria-labelledby={labelId}>
            {items.map(({ id, content, isDisabled }) => {
                const itemModifiers = [
                    ...(id === selectedItemId ? ['selected'] : []),
                    ...(isDisabled ? ['disabled'] : [])
                ];
                return (
                    <div
                        {...n('item', itemModifiers).withTestId().props}
                        key={id}
                        onClick={() => handleItemClick(id, isDisabled)}
                        onKeyDown={e => handleItemKeyDown(e, id, isDisabled)}
                        role="option"
                        aria-disabled={isDisabled}
                        aria-selected={id === selectedItemId}
                        tabIndex={itemsTabIndex}
                    >
                        {content}
                    </div>
                );
            })}
        </div>
    );

    const getSelectedItemContent = () => {
        const selectedItem = items.find(item => item.id === selectedItemId);
        return selectedItem && selectedItem.content ? selectedItem.content : null;
    };

    const renderSelectedItemContent = () => {
        if (isDropdownOpen || !selectedItemId) {
            return null;
        }
        const selectedContent = selectedItemContentOverride || getSelectedItemContent();
        if (selectedContent) {
            return (
                <div
                    {...n('selected-content').withTestId().props}
                    onClick={toggleDropdown}
                    onKeyDown={e => handleLabelKeyDown(e)}
                >
                    {selectedContent}
                </div>
            );
        }
        return null;
    };

    return (
        <div {...n('wrapper').withTestId().props}>
            <div
                {...n('label', modifiers).withTestId().props}
                onClick={toggleDropdown}
                onKeyDown={e => handleLabelKeyDown(e)}
                tabIndex={0}
                role="button"
                id={labelId}
            >
                {label}
                {' '}
                <Icon type="angleDown" />
            </div>
            {renderSelectedItemContent()}
            {renderList()}
        </div>
    );
};

ContentDropdown.propTypes = {
    label: PropTypes.string,
    selectedItemId: PropTypes.string,
    onClickItemCallback: PropTypes.func,
    closeOnItemClick: PropTypes.bool,
    selectedItemContentOverride: PropTypes.node,
    initiallyOpen: PropTypes.bool,
    items: PropTypes.arrayOf(PropTypes.shape({
        id: PropTypes.string,
        content: PropTypes.node,
        isDisabled: PropTypes.bool
    }))

};

ContentDropdown.defaultProps = {
    label: '',
    selectedItemId: '',
    onClickItemCallback: () => {},
    closeOnItemClick: true,
    selectedItemContentOverride: null,
    initiallyOpen: true,
    items: []
};
export default ContentDropdown;
