import { forwardRef, Ref, useState } from 'react';
import { Scrollbar, ScrollbarProps } from 'react-scrollbars-custom';
import { twMerge } from 'tailwind-merge';

export interface ScrollbarClasses {
    vertical?: {
        track?: string;
        thumb?: string;
    };
    horizontal?: {
        track?: string;
        thumb?: string;
    };
}

export interface ScrollbarsProps {
    /**
     * Will disable the horizontal scroll bar
     */
    noScrollX?: boolean;
    /**
     * Container for the content of the scrollbar .
     * @ignore
     */
    children?: React.ReactNode;
    /**
     * Tailwind styles object for the main container and included components.
     */
    classes?: ScrollbarClasses;
    /**
     * Will define a bottom margin for all children elements.
     */
    spacing?: string;
    /**
     * Will define a padding for the scrollbar container.
     */
    padding?: string;
    /**
     * AutoHide scrollbars when the mouse is not over the element.
     */
    autoHide?: boolean;
    /**
     * Set the size of the content to the container in style height.
     */
    translateContentSize?: boolean;
    /**
     * Scrollbar reference.
     */
    ref?: Ref<any>;
}

export const Scrollbars: React.FC<ScrollbarsProps & ScrollbarProps> = forwardRef((props, ref) => {
    const { noScrollX, children, autoHide, translateContentSize, className, classes, padding, spacing } = props;

    const [inUse, setInUse] = useState(false);

    return (
        <Scrollbar
            ref={ref}
            noDefaultStyles={true}
            translateContentSizeYToHolder={translateContentSize}
            noScrollX={noScrollX}
            removeTracksWhenNotUsed={true}
            onMouseEnter={() => (autoHide ? setInUse(true) : undefined)}
            onMouseLeave={() => (autoHide ? setInUse(false) : undefined)}
            renderer={(renderProps) => {
                const { elementRef, ...restProps } = renderProps;
                return (
                    <div {...restProps} ref={elementRef} className={twMerge(` flex-auto w-auto h-full ${className}`)} />
                );
            }}
            scrollerProps={{
                renderer: function scroller(scrollerProps) {
                    const { elementRef, ...restProps } = scrollerProps;
                    return (
                        <div
                            {...restProps}
                            ref={elementRef}
                            className="absolute top-0 right-0 bottom-0 left-0 overflow-x-hidden overflow-y-auto"
                        />
                    );
                },
            }}
            wrapperProps={{
                renderer: function wrapperProps(wrapperProps) {
                    const { elementRef, ...restProps } = wrapperProps;
                    return (
                        <div
                            {...restProps}
                            ref={elementRef}
                            className="absolute top-0 right-0 bottom-0 left-0 overflow-hidden"
                        />
                    );
                },
            }}
            contentProps={{
                renderer: function content(contentProps) {
                    const { elementRef, ...restProps } = contentProps;
                    return (
                        <div
                            {...restProps}
                            ref={elementRef}
                            style={undefined}
                            className={twMerge(` flex flex-col h-full ${spacing} ${padding}`)}
                        />
                    );
                },
            }}
            trackYProps={{
                renderer: function trackY(trackYProps) {
                    const { elementRef, ...restProps } = trackYProps;
                    return (
                        <div
                            {...restProps}
                            ref={elementRef}
                            className={twMerge(
                                ` w-2 absolute block overflow-hidden my-3 mr-3 rounded-full bg-gray-300 flex-auto bottom-0 top-0 right-0 select-none transition duration-200 ${
                                    autoHide ? (inUse ? 'opacity-100' : 'opacity-0') : 'opacity-100'
                                } ${classes?.vertical?.track}`,
                            )}
                        />
                    );
                },
            }}
            thumbYProps={{
                renderer: function thumbY(thumbYProps) {
                    const { elementRef, ...restProps } = thumbYProps;
                    return (
                        <div
                            {...restProps}
                            ref={elementRef}
                            className={twMerge(
                                ` w-2 absolute inline-block overflow-hidden rounded-full bg-gray-400 opacity-75 hover:opacity-100 cursor-pointer flex-auto select-none ${classes?.vertical?.thumb}`,
                            )}
                        />
                    );
                },
            }}
            trackXProps={{
                renderer: function trackX(trackXProps) {
                    const { elementRef, ...restProps } = trackXProps;
                    return (
                        <div
                            {...restProps}
                            ref={elementRef}
                            className={twMerge(
                                ` h-2 absolute inline-block overflow-hidden rounded-full bg-gray-300 flex-auto right-0 left-0 bottom-0 select-none ${
                                    autoHide ? (inUse ? 'opacity-100' : 'opacity-0') : 'opacity-100'
                                } ${classes?.vertical?.track}`,
                            )}
                        />
                    );
                },
            }}
            thumbXProps={{
                renderer: function thumbX(thumbXProps) {
                    const { elementRef, ...restProps } = thumbXProps;
                    return (
                        <div
                            {...restProps}
                            ref={elementRef}
                            className={twMerge(
                                ` h-2 absolute inline-block overflow-hidden rounded-full bg-gray-400 opacity-75 hover:opacity-100 cursor-pointer flex-auto select-none ${classes?.horizontal?.thumb}`,
                            )}
                        />
                    );
                },
            }}
        >
            {children}
        </Scrollbar>
    );
});

Scrollbars.defaultProps = {
    noScrollX: true,
};

Scrollbars.displayName = 'Scrollbar';

export default Scrollbars;
