import * as React from 'react'
import {
    ButtonPrimary,
    ButtonEmpty,
    ButtonGhost,
    ButtonDestructive,
    ButtonEmptyInverse,
    ButtonAnviPrimary,
    ButtonAnviEmpty,
    ButtonAnviEmptyInverse,
    ButtonAnviGhost,
    ListItem,
} from '@planview/pv-uikit'
import type { ButtonProps } from '@planview/pv-uikit'
import {
    ToolbarItem,
    ToolbarItemCollapsedView,
    ToolbarItemView,
} from '../wrapper/'

import type { DisplayOnType } from '../utils/'
import { useMergeRefs } from '../utils/refs'

export type ToolbarButtonProps = Omit<
    ButtonProps,
    'tabIndex' | 'children' | 'onClick' | 'size'
> & {
    /**
     * Target display of the button. Choose 'phone' to prevent collapsing.
     */
    displayOn?: DisplayOnType

    /**
     * Opt-in to override built-in behavior to remove the visible label of buttons in mobile breakpoint.
     * Set this to true to always show the visible label of button
     */
    preventLabelCollapse?: boolean

    /**
     * Limit the children more strictly since a string is required when converting to a list item and for adding an aria-label
     */
    children?: string | number

    /** Callback for when a user clicks on the button or activates it in the mobile menu. When activated from the collapsed menu, no event will be passed. */
    onClick?: (e?: React.MouseEvent) => void
}

const getAriaLabel = (
    props: ToolbarButtonProps,
    showLabels: boolean,
    children?: string | number,
    preventLabelCollapse = false
): string | undefined => {
    if (props['aria-label']) {
        return props['aria-label']
    }
    if (!children && props.tooltip) {
        return props.tooltip
    } else if (!showLabels && children && !preventLabelCollapse) {
        return children as string
    }
    return undefined
}

const asToolbarButton = (ElementType: typeof ButtonPrimary) => {
    const ForwardRefComponent: React.ForwardRefRenderFunction<
        HTMLButtonElement | undefined,
        ToolbarButtonProps
    > = (
        {
            children,
            onClick,
            onKeyDown,
            preventLabelCollapse = false,
            displayOn,
            ...otherProps
        }: ToolbarButtonProps,
        ref
    ) => {
        const buttonRef = React.useRef<HTMLButtonElement>(null)
        const mergedRef = useMergeRefs([ref, buttonRef])

        return (
            <ToolbarItem displayOn={displayOn}>
                <ToolbarItemView<HTMLButtonElement> refOverride={buttonRef}>
                    {(
                        _ref,
                        {
                            toolbarItemProps: {
                                focused: _focused,
                                ...toolbarItemProps
                            },
                            showLabels,
                        }
                    ) => {
                        const showTooltip =
                            !!otherProps.tooltip ||
                            (!showLabels && !!children && !!otherProps.icon)
                        const disabled = !!otherProps.disabled
                        return (
                            <ElementType
                                {...otherProps}
                                ref={mergedRef}
                                {...toolbarItemProps}
                                onClick={(ev) => {
                                    toolbarItemProps.onClick(ev)
                                    if (onClick && !disabled) {
                                        onClick(ev)
                                    }
                                }}
                                disabled={false} //otherProps can/will contain disabled flag we do NOT want on the button since it will mess with the listeners for roving tab index management
                                aria-disabled={
                                    !!disabled || otherProps['aria-disabled']
                                } //We explicitly pass the aria-disabled to the ui-kit button to make it look disabled.
                                onKeyDown={(ev) => {
                                    toolbarItemProps.onKeyDown(ev)
                                    if (onKeyDown && !disabled) {
                                        onKeyDown(ev)
                                    }
                                }}
                                tooltip={
                                    showTooltip
                                        ? otherProps.tooltip ||
                                          (children as string)
                                        : undefined
                                }
                                aria-label={getAriaLabel(
                                    otherProps,
                                    showLabels,
                                    children,
                                    preventLabelCollapse
                                )}
                            >
                                {!showLabels &&
                                otherProps.icon &&
                                !preventLabelCollapse
                                    ? undefined
                                    : children}
                            </ElementType>
                        )
                    }}
                </ToolbarItemView>
                <ToolbarItemCollapsedView>
                    <ListItem
                        label={(children || otherProps.tooltip || '') as string}
                        icon={otherProps.icon}
                        onActivate={() => {
                            if (onClick) {
                                onClick()
                            }
                        }}
                    />
                </ToolbarItemCollapsedView>
            </ToolbarItem>
        )
    }
    return ForwardRefComponent
}
export const ToolbarButtonDestructive = React.forwardRef(
    asToolbarButton(ButtonDestructive)
)
export const ToolbarButtonPrimary = React.forwardRef(
    asToolbarButton(ButtonPrimary)
)
export const ToolbarButtonEmpty = React.forwardRef(asToolbarButton(ButtonEmpty))
export const ToolbarButtonGhost = React.forwardRef(asToolbarButton(ButtonGhost))

export const ToolbarButtonEmptyInverse = React.forwardRef(
    asToolbarButton(ButtonEmptyInverse)
)

export const ToolbarButtonAnviPrimary = React.forwardRef(
    asToolbarButton(ButtonAnviPrimary)
)
export const ToolbarButtonAnviEmpty = React.forwardRef(
    asToolbarButton(ButtonAnviEmpty)
)
export const ToolbarButtonAnviEmptyInverse = React.forwardRef(
    asToolbarButton(ButtonAnviEmptyInverse)
)
export const ToolbarButtonAnviGhost = React.forwardRef(
    asToolbarButton(ButtonAnviGhost)
)
