import React, { startTransition, useCallback, useEffect, useRef, useState } from 'react';
import { LangCodes } from '../../constants/langCode';
import { getMessage } from '../../public/i18n';
import IconFont from '../IconFont';
import SelectOptions from '../SelectOptions';
import './style.css';

type LanguageSelectProps = {
    value: string;
    onChange: (value: string) => void;
    className?: string;
    langCodes: LangCodes;
    langLocal: { [key: string]: string };
    recentLangs: string[];
};

const LanguageSelect: React.FC<LanguageSelectProps> = ({ value, onChange, className, langCodes, langLocal, recentLangs }) => {
    const [showOptions, setShowOptions] = useState(false);
    const [searchLangCodes, setSearchLangCodes] = useState<LangCodes>([]);
    const [searchText, setSearchText] = useState('');

    const searchInputElementRef = useRef<HTMLInputElement>(null);
    const languageSelectElementRef = useRef<HTMLDivElement>(null);
    const onMouseDownRef = useRef((e: MouseEvent) => {
        const path = e.composedPath?.();

        if (languageSelectElementRef.current && path.indexOf(languageSelectElementRef.current) >= 0) { return; }

        setShowOptions(false);
    });

    const handleOptionClick = useCallback((value: string) => {
        onChange(value);
        setShowOptions(false);
    }, [onChange]);

    const handleInputChange = useCallback(() => {
        if (!searchInputElementRef.current) { return; }

        setSearchText(searchInputElementRef.current.value);
    }, []);

    const handleOptionsShow = useCallback(() => {
        if (!searchInputElementRef.current) { return; }

        const tempElement = searchInputElementRef.current.parentElement?.parentElement?.parentElement;
        tempElement && (tempElement.scrollTop = 0);
        searchInputElementRef.current.focus();
        searchInputElementRef.current.select();
    }, []);

    useEffect(() => {
        startTransition(() => {
            setSearchLangCodes(langCodes.filter(v => v.name.includes(searchText)));
        });
    }, [langCodes, searchText]);

    useEffect(() => {
        showOptions ? window.addEventListener('mousedown', onMouseDownRef.current, true) : window.removeEventListener('mousedown', onMouseDownRef.current, true);
    }, [showOptions]);

    return (
        <div
            className={`language-select${className ? ' ' + className : ''}`}
            ref={languageSelectElementRef}
            tabIndex={-1}
            onClick={() => setShowOptions(v => !v)}
        >
            <span className='language-select__badge'>
                <span className='language-select__badge-text'>{langLocal[value] ?? langLocal['']}</span>
                <IconFont iconName='#icon-GoChevronDown' />
            </span>
            <SelectOptions
                show={showOptions}
                onShow={handleOptionsShow}
                onClick={e => e.stopPropagation()}
            >
                {recentLangs?.map((v) => (v in langLocal && <div
                    className='language-select__option'
                    key={'recent-' + v}
                    onClick={() => handleOptionClick(v)}
                >
                    {langLocal[v]}
                </div>))}
                <div className='language-select__search'>
                    <IconFont iconName='#icon-search' />
                    <div className='language-select__search-input'>
                        <input type='text' placeholder={getMessage('sentenceSearchLanguages')} onChange={handleInputChange} ref={searchInputElementRef} />
                    </div>
                </div>
                {searchLangCodes.length > 0 ? searchLangCodes.map((v) => (<div
                    className='language-select__option'
                    key={v['code']}
                    onClick={() => handleOptionClick(v['code'])}
                >
                    {v['name']}
                </div>)) : <div className='language-select__no-result'>
                    {getMessage('sentenceNoResult')}
                </div>}
            </SelectOptions>
        </div>
    );
};

export default LanguageSelect;