"use client";
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import * as React from "react";
import { useEffect, useState } from "react";
import { useEditContext } from "../client/editContext";
import { useFieldModification } from "../client/fieldModificationStore";
import { useSlotContext } from "../views/editorSlotContext";
import { Button } from "../../components/ui/button";
import { Input } from "../../components/ui/input";
import { ArrowDown, ArrowUp, Plus } from "lucide-react";
import { DeleteIcon } from "../../components/ui/delete-icon";
function parseUrlEncoded(raw) {
    if (!raw)
        return [];
    const parts = raw.split("&").filter((p) => p.length > 0);
    const pairs = [];
    for (const part of parts) {
        const eqIndex = part.indexOf("=");
        const rawKey = eqIndex >= 0 ? part.substring(0, eqIndex) : part;
        const rawValue = eqIndex >= 0 ? part.substring(eqIndex + 1) : "";
        // Convert + to space before decode to align with Sitecore's HttpUtility behavior
        const key = decodeURIComponent(rawKey.replace(/\+/g, " "));
        const value = decodeURIComponent(rawValue.replace(/\+/g, " "));
        pairs.push({ key, value });
    }
    return pairs;
}
function toUrlEncoded(pairs) {
    const filtered = pairs.filter((p) => (p.key || "").trim().length > 0);
    const segments = filtered.map((p) => {
        const encKey = encodeURIComponent(p.key);
        const encValue = encodeURIComponent(p.value || "");
        // Replace %20 with + for compatibility with typical form encoding in Sitecore tools
        return `${encKey.replace(/%20/g, "+")}=${encValue.replace(/%20/g, "+")}`;
    });
    return segments.join("&");
}
export function NameValueListEditor({ field, readOnly }) {
    const editContext = useEditContext();
    const slotContext = useSlotContext();
    const [pairs, setPairs] = useState([]);
    const containerRef = React.useRef(null);
    const { isModified, isSaved } = useFieldModification(field.id, field.descriptor.item.id, field.descriptor.item.language, field.descriptor.item.version, slotContext?.fieldModificationStore);
    // Check if any input in this field is currently focused
    const isAnyInputFocused = () => {
        if (!containerRef.current)
            return false;
        const activeElement = document.activeElement;
        return containerRef.current.contains(activeElement);
    };
    useEffect(() => {
        // Don't update from server while user is actively editing
        // This prevents flickering when typing
        if (isAnyInputFocused())
            return;
        // While the field is dirty and not yet saved, keep showing the local state
        // to avoid flickering back to the previous server value during saves.
        if (isModified && !isSaved)
            return;
        // Prefer typed value, fallback to raw
        const fromValue = (Array.isArray(field.value) ? field.value : undefined);
        if (fromValue && fromValue.length > 0) {
            setPairs(fromValue.map((x) => ({ key: x.key || "", value: x.value || "" })));
        }
        else {
            setPairs(parseUrlEncoded(field.rawValue));
        }
    }, [
        field.value,
        field.rawValue,
        field.descriptor.item.id,
        field.id,
        isModified,
        isSaved,
    ]);
    if (!editContext)
        return null;
    const commit = async (next) => {
        const cleaned = next.filter((p) => (p.key || "").trim().length > 0);
        const raw = toUrlEncoded(cleaned);
        await editContext.operations.editField({
            field: field.descriptor,
            value: cleaned,
            rawValue: raw,
            refresh: "waitForQuietPeriod",
            originatingSlotId: slotContext?.slotId,
        });
    };
    const addRow = async () => {
        if (readOnly)
            return;
        const next = [...pairs, { key: "", value: "" }];
        setPairs(next);
    };
    const updateKey = async (index, key) => {
        if (readOnly)
            return;
        const next = pairs.map((p, i) => (i === index ? { ...p, key } : p));
        setPairs(next);
        await commit(next);
    };
    const updateValue = async (index, value) => {
        if (readOnly)
            return;
        const next = pairs.map((p, i) => (i === index ? { ...p, value } : p));
        setPairs(next);
        await commit(next);
    };
    const removeRow = async (index) => {
        if (readOnly)
            return;
        const next = pairs.filter((_, i) => i !== index);
        setPairs(next);
        await commit(next);
    };
    const moveRow = async (index, offset) => {
        if (readOnly)
            return;
        const newIndex = index + offset;
        if (newIndex < 0 || newIndex >= pairs.length)
            return;
        const next = [...pairs];
        const [item] = next.splice(index, 1);
        if (!item)
            return;
        next.splice(newIndex, 0, item);
        setPairs(next);
        await commit(next);
    };
    return (_jsxs("div", { ref: containerRef, className: `focus-shadow border-border-default rounded-sm border ${readOnly ? "bg-neutral-grey-5" : "bg-white"}`, children: [_jsx("div", { className: "border-border-default flex items-center justify-between border-b px-2 py-1.5", children: _jsx(Button, { type: "button", size: "sm", variant: "ghost", disabled: readOnly, onClick: addRow, className: "h-7 px-2", "aria-label": "Add entry", "data-testid": "add-entry-button", children: _jsx(Plus, { className: "h-4 w-4", strokeWidth: 1 }) }) }), _jsxs("div", { children: [pairs.length === 0 && (_jsx("div", { className: "text-neutral-grey-50 p-2 text-center text-xs", children: "No entries" })), pairs.map((pair, index) => (_jsxs("div", { className: "border-border-default flex items-center gap-1 border-b p-1 last:border-b-0", children: [_jsx(Input, { value: pair.key, placeholder: "Name", disabled: readOnly, className: "bg-neutral-grey-5 h-7 p-1 text-xs", onChange: (e) => updateKey(index, e.target.value) }), _jsx("span", { className: "text-neutral-grey-50 px-1", children: "=" }), _jsx(Input, { value: pair.value, placeholder: "Value", disabled: readOnly, className: "bg-neutral-grey-5 h-7 p-1 text-xs", onChange: (e) => updateValue(index, e.target.value) }), _jsxs("div", { className: "ml-auto flex items-center gap-0.5", children: [_jsx(Button, { type: "button", size: "icon", variant: "ghost", disabled: readOnly || index === 0, onClick: () => moveRow(index, -1), className: "h-7 w-7", "aria-label": "Move up", title: "Move up", children: _jsx(ArrowUp, { className: "h-4 w-4", strokeWidth: 1 }) }), _jsx(Button, { type: "button", size: "icon", variant: "ghost", disabled: readOnly || index === pairs.length - 1, onClick: () => moveRow(index, 1), className: "h-7 w-7", "aria-label": "Move down", title: "Move down", children: _jsx(ArrowDown, { className: "h-4 w-4", strokeWidth: 1 }) }), _jsx(Button, { type: "button", size: "icon", variant: "ghost", disabled: readOnly, onClick: () => removeRow(index), className: "text-neutral-grey-50 hover:bg-neutral-grey-5 hover:text-neutral-grey-50 h-7 w-7", "aria-label": "Delete", title: "Delete", children: _jsx(DeleteIcon, { size: "lg" }) })] })] }, index)))] })] }));
}
//# sourceMappingURL=NameValueListEditor.js.map