var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __rest = (this && this.__rest) || function (s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
            if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                t[p[i]] = s[p[i]];
        }
    return t;
};
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { ToolButton } from "../components/tool-button";
import { useRef, useState } from "react";
import { ResponsivePresenter } from "../../components/responsive";
import { LinkPopup } from "../popups/link-popup";
import { useToolbarLocation } from "../stores/toolbar-store";
import { MoreTools } from "../components/more-tools";
import { useRefValue } from "../../hooks/use-ref-value";
import { findMark, selectionToOffset } from "../../utils/prosemirror";
import { Flex, Link } from "@theme-ui/components";
import { ImageNode } from "../../extensions/image";
import { Link as LinkNode } from "../../extensions/link";
import { getMarkAttributes } from "@tiptap/core";
import { useHoverPopupContext } from "../floating-menus/hover-popup/context";
export function LinkSettings(props) {
    const { editor } = props;
    const isBottom = useToolbarLocation() === "bottom";
    if (!editor.isActive("link") || !isBottom)
        return null;
    return (_jsx(MoreTools, Object.assign({}, props, { autoOpen: true, autoCloseOnUnmount: true, popupId: "linkSettings", tools: editor.isEditable
            ? ["openLink", "editLink", "removeLink", "copyLink"]
            : ["openLink", "copyLink"] })));
}
export function AddLink(props) {
    const { editor } = props;
    const isActive = editor.isActive("link");
    if (isActive)
        return _jsx(EditLink, Object.assign({}, props, { icon: "linkEdit" }));
    return (_jsx(LinkTool, Object.assign({}, props, { onDone: (attributes) => editor.commands.toggleLink(attributes), onClick: () => {
            if (!editor)
                return;
            const selectedText = editor.state.doc.textBetween(editor.state.selection.from, editor.state.selection.to);
            return { title: selectedText, href: "" };
        } })));
}
export function AddInternalLink(props) {
    const { editor } = props;
    const isActive = editor.isActive(LinkNode.name);
    return (_jsx(ToolButton, Object.assign({}, props, { disabled: isActive, onClick: () => __awaiter(this, void 0, void 0, function* () {
            var _a, _b;
            const link = yield ((_b = (_a = editor.storage).createInternalLink) === null || _b === void 0 ? void 0 : _b.call(_a));
            if (!link)
                return;
            const selectedText = editor.state.doc.textBetween(editor.state.selection.from, editor.state.selection.to);
            editor.commands.setLink(Object.assign(Object.assign({}, link), { title: selectedText || link.title }));
        }) })));
}
export function EditLink(props) {
    const { editor } = props;
    const { selectedNode: _selectedNode, hide } = useHoverPopupContext();
    const selectedNode = useRefValue(_selectedNode || selectionToOffset(editor.state));
    const { node } = _selectedNode || {};
    const link = node ? findMark(node, LinkNode.name) : null;
    const attrs = (link === null || link === void 0 ? void 0 : link.attrs) || getMarkAttributes(editor.state, LinkNode.name);
    if (attrs && isInternalLink(attrs.href))
        return (_jsx(ToolButton, Object.assign({}, props, { onClick: () => __awaiter(this, void 0, void 0, function* () {
                var _a, _b;
                hide();
                const link = yield ((_b = (_a = editor.storage).createInternalLink) === null || _b === void 0 ? void 0 : _b.call(_a));
                if (!link)
                    return;
                const { from, to } = editor.state.selection;
                if (selectedNode.current)
                    editor.commands.setTextSelection(selectedNode.current);
                editor.commands.setLink(link);
                if (selectedNode.current)
                    editor.commands.setTextSelection({ from, to });
            }) })));
    return (_jsx(LinkTool, Object.assign({}, props, { isEditing: true, onDone: (attributes) => {
            if (selectedNode.current)
                editor.chain().focus().setTextSelection(selectedNode.current).run();
            editor.commands.setLink(attributes);
            hide();
        }, onClick: () => {
            if (!selectedNode.current)
                return;
            const { node } = selectedNode.current;
            if (!node)
                return;
            const selectedText = node.textContent;
            const mark = findMark(node, "link");
            if (!mark)
                return;
            return {
                title: selectedText,
                href: mark.attrs.href
            };
        } })));
}
export function RemoveLink(props) {
    const { editor } = props;
    const { selectedNode, hide } = useHoverPopupContext();
    if (!editor.isEditable)
        return null;
    return (_jsx(ToolButton, Object.assign({}, props, { toggled: false, onClick: () => {
            if (selectedNode)
                editor.commands.setTextSelection({
                    from: selectedNode.from,
                    to: selectedNode.to
                });
            editor.chain().focus().unsetLink().run();
            hide();
        } })));
}
export function OpenLink(props) {
    const { editor } = props;
    const { selectedNode: _selectedNode, hide } = useHoverPopupContext();
    const selectedNode = useRefValue(_selectedNode || selectionToOffset(editor.state));
    const { node } = selectedNode.current || {};
    const link = node ? findMark(node, "link") : null;
    if (!link)
        return null;
    const href = link === null || link === void 0 ? void 0 : link.attrs.href;
    return (_jsxs(Flex, { sx: { alignItems: "center" }, children: [_jsx(Link, { href: href, onClick: (e) => {
                    var _a, _b;
                    e.preventDefault();
                    (_b = (_a = editor.storage).openLink) === null || _b === void 0 ? void 0 : _b.call(_a, href);
                    hide();
                }, target: "_blank", variant: "body", sx: {
                    fontSize: "subBody",
                    fontFamily: "body",
                    mr: 1,
                    color: "accent",
                    maxWidth: [150, 250],
                    overflow: "hidden",
                    textOverflow: "ellipsis",
                    whiteSpace: "nowrap",
                    ":visited": { color: "accent" },
                    ":hover": { color: "accent", opacity: 0.8 }
                }, children: href }), _jsx(ToolButton, Object.assign({}, props, { toggled: false, onClick: () => {
                    var _a, _b;
                    (_b = (_a = editor.storage).openLink) === null || _b === void 0 ? void 0 : _b.call(_a, href);
                    hide();
                } }))] }));
}
export function CopyLink(props) {
    const { editor } = props;
    const { selectedNode: _selectedNode, hide } = useHoverPopupContext();
    const selectedNode = useRefValue(_selectedNode || selectionToOffset(editor.state));
    const { node } = selectedNode.current || {};
    const link = node ? findMark(node, "link") : null;
    if (!link)
        return null;
    const href = link === null || link === void 0 ? void 0 : link.attrs.href;
    return (_jsx(ToolButton, Object.assign({}, props, { toggled: false, onClick: () => {
            var _a, _b, _c, _d;
            (_b = (_a = editor.storage).copyToClipboard) === null || _b === void 0 ? void 0 : _b.call(_a, href, `<a href="${href}">${((_d = (_c = selectedNode.current) === null || _c === void 0 ? void 0 : _c.node) === null || _d === void 0 ? void 0 : _d.textContent) || (link === null || link === void 0 ? void 0 : link.attrs.title)}</a>`);
            hide();
        } })));
}
function LinkTool(props) {
    const { isEditing, onClick, onDone, editor } = props, toolProps = __rest(props, ["isEditing", "onClick", "onDone", "editor"]);
    const buttonRef = useRef(null);
    const [isOpen, setIsOpen] = useState(false);
    const [linkDefinition, setLinkDefinition] = useState();
    const isImageActive = editor.isActive(ImageNode.name);
    return (_jsxs(_Fragment, { children: [_jsx(ToolButton, Object.assign({}, toolProps, { buttonRef: buttonRef, onClick: () => {
                    const result = onClick();
                    if (!result)
                        return;
                    setLinkDefinition(result);
                    setIsOpen(true);
                }, toggled: isOpen })), _jsx(ResponsivePresenter, { mobile: "sheet", desktop: "popup", position: {
                    target: buttonRef.current || undefined,
                    isTargetAbsolute: true,
                    location: "below",
                    align: "center",
                    yOffset: 5
                }, title: isEditing ? "Edit link" : "Insert link", isOpen: isOpen, items: [], onClose: () => {
                    setIsOpen(false);
                    editor.commands.focus();
                }, focusOnRender: false, children: _jsx(LinkPopup, { link: linkDefinition, isEditing: isEditing, isImageActive: isImageActive, onClose: () => setIsOpen(false), onDone: (link) => {
                        onDone(link);
                        setIsOpen(false);
                    } }) })] }));
}
function isInternalLink(href) {
    return typeof href === "string" ? href.startsWith("nn://") : false;
}
