import * as React from 'react';
import * as _ from 'lodash';
import * as DefaultStyles from './style';

export namespace DropDownItem {
    export interface Props {
        /**
         * Indicates if the item is focused, changing the style depending on the value
         */
        focused: boolean;
        /**
         * Chunk to be highlighted inside the value
         */
        highlightedChunk?: string;
        /**
         * Function called when the user clicks in the component
         */
        onClick: (event, value: { toString: () => string }) => void;
        /**
         * Function called when the mouse enters in the component
         */
        onMouseEnter: (event, value: { toString: () => string }, position: number) => void;
        /**
         * Position of the component in the list
         */
        position: number;
        /**
         * Prop to customize styles
         */
        styles?: Styles;
        /**
         * Text displayed
         */
        value: { toString: () => string };

        id?: string;

        name?: string;

    }

    export interface Styles {
        /**
         * Styles for the highlighted chunks
         */
        HighlightedItemChunk?: any;
        /**
         * Styles for the component if focused
         */
        ListItemFocused?: any;
        /**
         * Styles for the component if not focused
         */
        ListItemNotFocused?: any;
        /**
         * Styles for the not highlighted chunks
         */
        RegularItemChunk?: any;
    }
}

/**
 * Component that displays an item with a description. Useful for rendering the dropdown component options
 * 
 * @version 1.0.0
 * 
 */
export const DropDownItem = (props: DropDownItem.Props) => {
    const handleItemClick = () => {
        props.onClick(event, props.value);
    };

    const handleItemMouseEnter = () => {
        props.onMouseEnter(event, props.value, props.position);
    };

    /**
     * Renders a component with key a string inside
    */
    const renderValue = (Component: any, value: string, className: string, index: number) => {
        return (
            <Component className={className} key={index}>
                {value}
            </Component>
        );
    };

    /**
     * Divides the value in chunks, indicating which ones should be highlighted
    */
    const processChunksDisplay = (value: string, chunkToHighlight?: string) => {
        const upperCaseChunkToHighlight = chunkToHighlight ? chunkToHighlight.toUpperCase() : '';
        const chunksRegex = new RegExp(`(${upperCaseChunkToHighlight})`, 'i');
        const chunks = value.split(chunksRegex);
        return chunks.filter((chunk) => (chunk !== '')).map((chunk, index) => ({
            chunk,
            highlighted: chunk.toUpperCase() === upperCaseChunkToHighlight
        }));
    };

    /**
     * Renders the value, highlighting the corresponding chunks
    */
    const renderChunks = (Styles: DropDownItem.Styles) => {
        const chunks = processChunksDisplay(props.value.toString(), props.highlightedChunk);
        return chunks.map((chunkData, index) => (
            chunkData.highlighted ?
                (
                    renderValue(Styles.HighlightedItemChunk, chunkData.chunk, 'drop-down-item-highlighted-value', index)
                ) : (
                    renderValue(Styles.RegularItemChunk, chunkData.chunk, 'drop-down-item-value', index)
                )
        ))
    };

    const Styles: DropDownItem.Styles = _.merge(DefaultStyles, props.styles);
    const ListItemComponent = props.focused ? Styles.ListItemFocused : Styles.ListItemNotFocused;
    return (
        <ListItemComponent
            className={'drop-down-item-container'}
            id={props.id && props.id + '-list-item'}
            onClick={handleItemClick}
            onMouseEnter={handleItemMouseEnter}
            name={props.name && props.name + '-list-item'}
        >
            {
                props.highlightedChunk ?
                    renderChunks(Styles)
                    :
                    renderValue(Styles.RegularItemChunk, props.value.toString(), 'drop-down-item-value', 0)
            }
        </ListItemComponent>
    );
}
