import React, { useRef, useEffect, useState } from 'react';
import classnames from 'classnames';
import { CSSTransition } from 'react-transition-group';
import Portal from '../portal';

type TriggerType = 'click' | 'hover' | 'contextMenu';

export type DropdownProps = {
    defaultVisible?: boolean,
    visible?: boolean,
    onVisibleChange?: (visible: boolean) => void,
    trigger?: TriggerType[],
    placement?: 'topLeft' | 'topCenter' | 'topRight' | 'bottomLeft' | 'bottomCenter' | 'bottomRight',
    overlay?: React.ReactNode,
    overlayClassName?: string,
    overlayStyle?: React.CSSProperties,
    prefixCls?: string,
    className?: string,
    style?: React.CSSProperties,
    children?: React.ReactNode,
} & typeof defaultProps;

const defaultProps = {
    prefixCls: 'ty-dropdown',
    placement: 'bottomLeft',
    defaultVisible: false,
};

const updatePosition = (placement: string) => {
    const overlayPosition: React.CSSProperties = {};
    switch (placement) {
        case 'topLeft':
            overlayPosition.bottom = '100%';
            overlayPosition.left = 0;
            break;

        case 'topCenter':
            overlayPosition.bottom = '100%';
            overlayPosition.left = '50%';
            overlayPosition.transform = 'translateX(-50%)';
            break;

        case 'topRight':
            overlayPosition.bottom = '100%';
            overlayPosition.right = 0;
            break;

        default:
            overlayPosition.top = '100%';
            overlayPosition.left = 0;
            break;
    }

    return overlayPosition;
};

let timeout: any = null;

const Dropdown = (props: DropdownProps) => {
    const { overlay, placement, prefixCls, className, overlayClassName, style, overlayStyle, children } = props;
    const cls = classnames(prefixCls, className);
    const overlayCls = classnames(`${prefixCls}__overlay`, overlayClassName);
    const containerRef = useRef<HTMLDivElement>(null);
    const overlayRef = useRef<HTMLDivElement>(null);
    const [position, setPosition] = useState<React.CSSProperties>({});
    const [visible, setVisible] = useState(('visible' in props) ? props.visible : props.defaultVisible);

    const show = () => {
        clearTimeout(timeout);
        timeout = setTimeout(() => setVisible(true), 250);
    };

    const hide = () => {
        clearTimeout(timeout);
        timeout = setTimeout(() => setVisible(false), 150);
    };

    useEffect(() => {
        const updatedStyle = updatePosition(placement);
        setPosition(updatedStyle);
        setVisible(false);

        if (containerRef.current) {
            containerRef.current.addEventListener('mouseenter', show);
            containerRef.current.addEventListener('mouseleave', hide);
        }
        if (overlayRef.current) {
            overlayRef.current.addEventListener('mouseenter', show);
            overlayRef.current.addEventListener('mouseleave', hide);
        }

        return () => {
            if (containerRef.current) {
                containerRef.current.removeEventListener('mouseenter', show);
                containerRef.current.removeEventListener('mouseleave', hide);
            }
            if (overlayRef.current) {
                overlayRef.current.removeEventListener('mouseenter', show);
                overlayRef.current.removeEventListener('mouseleave', hide);
            }
        };
    }, []);

    return (
        <div className={cls} style={style}>
            <div ref={containerRef}>{children}</div>
            <Portal>
                <CSSTransition
                    mountOnEnter={true}
                    in={visible}
                    classNames={`${prefixCls}__overlay_slide`}
                    timeout={{ enter: 0, exit: 300 }}>
                    <div ref={overlayRef} className={overlayCls} style={{ ...overlayStyle, ...position }}>
                        {overlay}
                    </div>
                </CSSTransition>
            </Portal>
        </div>
    );
};

Dropdown.defaultProps = defaultProps;

export default Dropdown;
