import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { forwardRef, useState, useRef, useContext, useEffect } from 'react';
import styled, { css } from 'styled-components';
import Button from '../Button';
import Popover from '../Popover';
import BareButton from '../Button/BareButton';
import { defaultThemeProp } from '../../theme';
import { useBreakpoint, useConsolidatedRef, useI18n, useUID, useModalContext, useOS, useTestIds } from '../../hooks';
import { documentIsAvailable, tryCatch, withTestIds, disallowedURI } from '../../utils';
import { calculateFontSize, readableColor } from '../../styles';
import AppShellContext from '../AppShell/AppShellContext';
import { Keyboard } from '../Badges';
import { StyledKeyboard } from '../Badges/Keyboard';
import Flex from '../Flex';
import Icon, { StyledIcon, registerIcon } from '../Icon';
import * as openIcon from '../Icon/icons/open.icon';
import VisuallyHiddenText from '../VisuallyHiddenText';
import { useFullscreenContext } from '../Fullscreen';
import { getLinkTestIds } from './Link.test-ids';
export const StyledLinkPopover = styled.div(({ theme, preview }) => css `
    background-color: ${theme.components.tooltip['background-color']};
    z-index: ${theme.base['z-index'].tooltip};

    ${preview &&
    css `
      padding: calc(${theme.base.spacing} / 4);
    `}
  `);
StyledLinkPopover.defaultProps = defaultThemeProp;
export const StyledLinkPopoverBtn = styled(BareButton)(({ theme }) => {
    const contrastColor = tryCatch(() => readableColor(theme.components.tooltip['background-color']));
    const fontSize = calculateFontSize(theme.base['font-size'], theme.base['font-scale']);
    return css `
    position: relative;
    display: inline-flex;
    align-items: center;
    z-index: 1;
    padding: 0 ${theme.base.spacing};
    min-height: 1.5rem;
    line-height: 1;
    color: ${contrastColor};
    font-size: ${fontSize.xs};
    text-decoration: none;

    /* FIXME: Button selector specificity... */
    & + & {
      margin: 0;
    }

    & + &::before {
      content: '';
      position: absolute;
      inset-inline-start: 0;
      inset-block: 0;
      width: 1px; /* stylelint-disable-line unit-allowed-list */
      background-color: ${contrastColor};
      opacity: ${theme.base.transparency['transparent-3']};
    }

    &:hover,
    &:active {
      text-decoration: underline;
    }

    &:focus {
      box-shadow:
        inset 0 0 0 0.0625rem ${theme.base.palette.light},
        0 0 0.125rem 0.0625rem ${theme.base.palette.interactive};
    }
  `;
});
StyledLinkPopoverBtn.defaultProps = defaultThemeProp;
export const StyledLinkPreviewPopoverText = styled.div ``;
export const StyledLinkPreviewPopoverBtn = styled(StyledLinkPopoverBtn)(({ theme }) => {
    return css `
    padding: calc(${theme.base.spacing} / 2);

    & + & {
      padding-inline-start: calc(${theme.base.spacing} - ${theme.base.spacing} / 4);
      padding-inline-end: calc(${theme.base.spacing} / 4);
    }

    &:hover,
    &:active {
      text-decoration: none;
      ${StyledLinkPreviewPopoverText} span {
        text-decoration: underline;
      }
      ${StyledLinkPreviewPopoverText} ${StyledKeyboard} span {
        text-decoration: none;
      }
    }

    ${StyledLinkPreviewPopoverText} {
      display: flex;
      justify-content: space-between;
      align-items: center;
      width: 100%;
    }

    ${StyledKeyboard} {
      color: ${theme.base.palette.light};
      background-color: ${theme.base.colors.gray.dark};
      border-color: ${theme.base.colors.gray.medium};
      inset-block-start: unset;
      margin-inline: calc(${theme.base.spacing} / 4);

      &:first-of-type {
        margin-inline-start: calc(${theme.base.spacing} / 2);
      }

      &:last-of-type {
        margin-inline-end: calc(${theme.base.spacing} / 2);
      }
    }
  `;
});
StyledLinkPreviewPopoverBtn.defaultProps = defaultThemeProp;
export const StyledLink = styled(Button) `
  &:has(> img) {
    display: inline-block;

    ${StyledIcon} {
      vertical-align: top;
    }
  }
`;
StyledLink.defaultProps = defaultThemeProp;
registerIcon(openIcon);
const Link = forwardRef(function Link({ testId, href: hrefProp, variant = 'link', icon = false, previewable: showPreviewOpenInTabPopoverProp = false, onPreview, target: targetProp, children, ...restProps }, ref) {
    const href = disallowedURI.test(hrefProp) ? undefined : hrefProp;
    const { initialized: inModal } = useModalContext();
    const fullscreen = useFullscreenContext();
    const inFullscreen = !!(fullscreen && fullscreen[0]);
    const { previewTriggerRef } = useContext(AppShellContext);
    const uid = useUID();
    const linkRef = useConsolidatedRef(ref);
    const [popover, setPopover] = useState(false);
    const [popoverHideDelay, setPopoverHideDelay] = useState('short');
    const [previewPopover, setPreviewPopover] = useState(false);
    const previewBtnRef = useRef(null);
    const isSmallOrAbove = useBreakpoint('sm');
    const t = useI18n();
    const { macintosh } = useOS();
    const contextMenuOpened = useRef(false);
    const testIds = useTestIds(testId, getLinkTestIds);
    const mousePositionRef = useRef({ x: 0, y: 0 });
    const virtualElementCoordsRef = useRef({ x: 0, y: 0 });
    const virtualElementRef = useRef({
        get contextElement() {
            return linkRef.current ?? undefined;
        },
        getBoundingClientRect: () => {
            return {
                width: 0,
                height: 0,
                top: virtualElementCoordsRef.current.y,
                bottom: virtualElementCoordsRef.current.y,
                left: virtualElementCoordsRef.current.x,
                right: virtualElementCoordsRef.current.x,
                x: virtualElementCoordsRef.current.x,
                y: virtualElementCoordsRef.current.y,
                toJSON() {
                    return JSON.stringify(this);
                }
            };
        }
    });
    const previewable = showPreviewOpenInTabPopoverProp && !inModal && !inFullscreen;
    let crossOrigin;
    try {
        if (href) {
            const url = new URL(href, document.location.href);
            crossOrigin = documentIsAvailable
                ? /^https?:$/.test(url.protocol) && document.location.origin !== url.origin
                : false;
        }
        else {
            crossOrigin = false;
        }
    }
    catch {
        crossOrigin = false;
    }
    const target = crossOrigin ? '_blank' : targetProp;
    const showPopover = () => {
        if (isSmallOrAbove && !previewPopover) {
            setPopover(true);
        }
    };
    const showPreviewPopover = () => {
        if (isSmallOrAbove && !popover && !contextMenuOpened.current)
            setPreviewPopover(true);
    };
    const hidePopover = () => {
        setPopover(false);
    };
    const hidePreviewPopover = () => {
        setPreviewPopover(false);
    };
    const onBlurLink = () => {
        contextMenuOpened.current = false;
        hidePreviewPopover();
    };
    const onPreviewClick = () => {
        previewTriggerRef.current = linkRef.current;
        if (href !== undefined) {
            onPreview?.({ href });
        }
    };
    const onKeyUp = (e) => {
        if (e.getModifierState('Alt') && e.code === 'KeyP') {
            onPreviewClick();
        }
    };
    useEffect(() => {
        if (popoverHideDelay === 'none' && !popover && !previewPopover) {
            setPopoverHideDelay('short');
        }
    }, [popoverHideDelay, popover, previewPopover]);
    useEffect(() => {
        const onKeyDown = ({ key }) => {
            if (key === 'Escape' && (popover || previewPopover)) {
                setPopoverHideDelay('none');
                setPopover(false);
                setPreviewPopover(false);
            }
        };
        document.addEventListener('keydown', onKeyDown);
        return () => {
            document.removeEventListener('keydown', onKeyDown);
        };
    }, [popover, previewPopover]);
    return (_jsxs(_Fragment, { children: [_jsxs(StyledLink, { "data-testid": testIds.root, href: href, variant: variant, ref: linkRef, target: target, ...restProps, "aria-describedby": previewable ? `${uid}-preview-instructions` : undefined, onMouseEnter: showPreviewOpenInTabPopoverProp
                    ? (e) => {
                        mousePositionRef.current = { x: e.clientX, y: e.clientY };
                        showPopover();
                    }
                    : undefined, onMouseLeave: hidePopover, onMouseMove: (e) => {
                    mousePositionRef.current = { x: e.clientX, y: e.clientY };
                }, onFocus: showPreviewOpenInTabPopoverProp
                    ? () => {
                        showPreviewPopover();
                    }
                    : undefined, onBlur: onBlurLink, onKeyUp: onKeyUp, onContextMenu: () => {
                    contextMenuOpened.current = true;
                    setPopoverHideDelay('none');
                    hidePreviewPopover();
                    hidePopover();
                }, children: [children, target === '_blank' && _jsx(VisuallyHiddenText, { children: t('opens_in_a_new_tab') }), !icon && target === '_blank' && _jsx(Icon, { name: 'open' })] }), previewable && (_jsxs(Popover, { "data-testid": testIds.previewPopover, show: previewPopover, placement: 'top', groupId: 'tooltip', showDelay: 'short', hideDelay: popoverHideDelay, target: linkRef.current, as: StyledLinkPopover, arrow: true, preview: true, portal: true, onHide: hidePreviewPopover, onClick: (e) => {
                    e.stopPropagation();
                }, children: [_jsx(StyledLinkPreviewPopoverBtn, { "data-testid": testIds.preview, preview: true, type: 'button', ref: previewBtnRef, onClick: onPreviewClick, tabIndex: '-1', children: _jsxs(StyledLinkPreviewPopoverText, { children: [_jsx("span", { children: t('preview') }), _jsxs(Flex, { container: { inline: true, justify: 'end' }, children: [_jsx(Keyboard, { keyName: 'Alt' }), _jsx(Keyboard, { keyName: 'P' })] })] }) }), _jsx(StyledLinkPreviewPopoverBtn, { "data-testid": testIds.newTab, forwardedAs: 'a', href: href, target: '_blank', rel: 'noreferrer', tabIndex: '-1', children: _jsxs(StyledLinkPreviewPopoverText, { children: [_jsx("span", { children: t('link_open_in_tab_text') }), _jsxs(Flex, { container: { inline: true, justify: 'end' }, children: [_jsx(Keyboard, { keyName: 'CommandOrControl' }), _jsx(Keyboard, { keyName: 'Enter' })] })] }) })] })), _jsxs(Popover, { "data-testid": testIds.previewPopover, show: popover, placement: 'top', groupId: 'tooltip', showDelay: 'short', hideDelay: popoverHideDelay, target: virtualElementRef.current, onMouseEnter: showPopover, onMouseLeave: hidePopover, as: StyledLinkPopover, arrow: true, portal: true, onClick: (e) => {
                    e.stopPropagation();
                }, onShow: () => {
                    const clientRects = linkRef.current?.getClientRects() ?? [];
                    const { x: mouseX, y: mouseY } = mousePositionRef.current;
                    const containingRect = Array.from(clientRects).find(
                    // Assumes the rects are returned in order of appearance (left to right, top down) and don't overlap
                    rect => mouseY < rect.bottom && mouseX < rect.right);
                    if (containingRect) {
                        virtualElementCoordsRef.current = {
                            x: mouseX,
                            y: containingRect.top
                        };
                    }
                }, children: [previewable && (_jsx(StyledLinkPopoverBtn, { "data-testid": testIds.preview, preview: true, type: 'button', ref: previewBtnRef, onClick: onPreviewClick, tabIndex: '-1', children: t('preview') })), _jsx(StyledLinkPopoverBtn, { "data-testid": testIds.newTab, forwardedAs: 'a', href: href, target: '_blank', rel: 'noreferrer', tabIndex: '-1', children: t('link_open_in_tab_text') })] }), previewable && (_jsx("span", { id: `${uid}-preview-instructions`, hidden: true, children: t('preview_link_instruction', [macintosh ? 'option' : 'alt']) }))] }));
});
export default withTestIds(Link, getLinkTestIds);
//# sourceMappingURL=Link.js.map