"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DisplayEditModeValueEditorRender = exports.ValueEditorRender = exports.XValueEditor = void 0;
const tslib_1 = require("tslib");
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = tslib_1.__importStar(require("react"));
const styled_components_1 = tslib_1.__importDefault(require("styled-components"));
const DataTypes_1 = require("@appglue/common/dist/Common/Data/DataTypes");
const Number_1 = require("./DataEditing/Number");
const Boolean_1 = require("./DataEditing/Boolean");
const String_1 = require("./DataEditing/String");
const Date_1 = require("./DataEditing/Date");
const DesignUI_1 = require("./DataEditing/DesignUI");
const core_1 = require("@material-ui/core");
const Object_1 = require("./DataEditing/Object");
const File_1 = require("./DataEditing/File");
const StyledButton_1 = require("./BuildlingBlocks/StyledButton");
const UILayer_1 = require("./BuildlingBlocks/UILayer");
const Link_1 = require("./BuilderUI/Link");
function XValueEditor({ forData, value: propValue, onUpdate, mode, navigate, editMode }) {
    const [value, setValue] = (0, react_1.useState)(propValue);
    const ref = react_1.default.useRef(null);
    (0, react_1.useEffect)(() => {
        setValue(propValue);
    }, [propValue, setValue]);
    const onValueUpdate = (newValue) => {
        setValue(newValue);
        onUpdate(newValue);
    };
    const onSetEdit = (0, react_1.useCallback)((event) => {
        // if (ref.current && ref.current !== document.activeElement) {
        //     ref.current.focus();
        // }
        if (navigate) {
            switch (event.key) {
                case "Down": // IE/Edge specific value
                case "ArrowDown":
                    if (ref.current instanceof HTMLSelectElement) {
                        ref.current.focus();
                    }
                    else {
                        navigate("Down");
                    }
                    break;
                case "Up": // IE/Edge specific value
                case "ArrowUp":
                    navigate("Up");
                    break;
                case "Left": // IE/Edge specific value
                case "ArrowLeft":
                    // check if current focused element is input element and cursor is placed before first character.
                    if (ref.current) {
                        if (ref.current instanceof HTMLInputElement &&
                            ["text"].includes(ref.current.getAttribute("type") || "") &&
                            (ref.current.selectionEnd || 0) === 0) {
                            navigate("Left");
                        }
                        else if (!(ref.current instanceof HTMLInputElement)) {
                            navigate("Left");
                        }
                        else if (ref.current instanceof HTMLInputElement &&
                            !["text"].includes(ref.current.getAttribute("type") || "")) {
                            navigate("Left");
                        }
                    }
                    else {
                        navigate("Left");
                    }
                    break;
                case "Right": // IE/Edge specific value
                case "ArrowRight":
                    // check if current focused element is input element and cursor is placed after last character.
                    if (ref.current) {
                        if (ref.current instanceof HTMLInputElement &&
                            ["text"].includes(ref.current.getAttribute("type") || "") &&
                            (ref.current.selectionEnd || 0) >= (value || "").length - 1) {
                            navigate("Right");
                        }
                        else if (!(ref.current instanceof HTMLInputElement)) {
                            navigate("Right");
                        }
                        else if (ref.current instanceof HTMLInputElement &&
                            !["text"].includes(ref.current.getAttribute("type") || "")) {
                            navigate("Right");
                        }
                    }
                    else {
                        navigate("Right");
                    }
                    break;
                case "Tab":
                    navigate("Tab");
                    break;
                default:
                    return; // Quit when this doesn't handle the key event.
            }
        }
    }, [navigate, ref, value]);
    react_1.default.useEffect(() => {
        // listen the keyboard events only for edit mode and display mode edit.
        if (mode === "display_mode_edit" || mode === "edit_mode") {
            window.addEventListener("keydown", onSetEdit);
        }
        return () => {
            if (mode === "display_mode_edit" || mode === "edit_mode") {
                window.removeEventListener("keydown", onSetEdit);
            }
        };
    }, [mode, onSetEdit]);
    switch (forData.type) {
        case DataTypes_1.DataTypes.BOOLEAN:
            return ((0, jsx_runtime_1.jsx)(exports.ValueEditorRender, { forData: forData, value: value, onUpdate: onValueUpdate, mode: mode, ref: ref, displayRenderUI: Boolean_1.DisplayModeBooleanValueEditor, editRenderUI: Boolean_1.EditModeBooleanValueEditor, editMode: editMode || "inline" }));
        case DataTypes_1.DataTypes.STRING:
            return ((0, jsx_runtime_1.jsx)(exports.ValueEditorRender, { forData: forData, value: value, onUpdate: onValueUpdate, mode: mode, ref: ref, displayRenderUI: String_1.DisplayModeStringValueEditor, editRenderUI: String_1.EditModeStringValueEditor, editMode: editMode || "inline" }));
        case DataTypes_1.DataTypes.DATE:
            return ((0, jsx_runtime_1.jsx)(exports.ValueEditorRender, { forData: forData, value: value, onUpdate: onValueUpdate, mode: mode, ref: ref, displayRenderUI: Date_1.DisplayModeDateValueEditor, editRenderUI: Date_1.EditModeDateValueEditor, editMode: editMode || "inline" }));
        case DataTypes_1.DataTypes.NUMBER:
            return ((0, jsx_runtime_1.jsx)(exports.ValueEditorRender, { forData: forData, value: value, onUpdate: onValueUpdate, mode: mode, ref: ref, displayRenderUI: Number_1.DisplayModeNumberValueEditor, editRenderUI: Number_1.EditModeNumberValueEditor, editMode: editMode || "inline" }));
        case DataTypes_1.DataTypes.FILE:
            return ((0, jsx_runtime_1.jsx)(exports.ValueEditorRender, { forData: forData, value: value, onUpdate: onValueUpdate, mode: mode, ref: ref, displayRenderUI: File_1.DisplayModeFileValueEditor, editRenderUI: File_1.EditModeFileValueEditor, editMode: editMode || "inline" }));
        case DataTypes_1.DataTypes.OBJECT:
            return ((0, jsx_runtime_1.jsx)(exports.ValueEditorRender, { forData: forData, value: value, onUpdate: onValueUpdate, mode: mode, ref: ref, displayRenderUI: Object_1.DisplayModeObjectValueEditor, editRenderUI: Object_1.EditModeObjectValueEditor, editMode: editMode || "inline" }));
        default:
            return null;
    }
}
exports.XValueEditor = XValueEditor;
exports.ValueEditorRender = react_1.default.forwardRef(({ editRenderUI, displayRenderUI, forData, value, onUpdate, mode, navigate, editMode }, ref) => {
    const [updated, setUpdated] = react_1.default.useState(value);
    (0, react_1.useEffect)(() => {
        setUpdated(value);
    }, [value]);
    let content;
    if (Array.isArray(value) && typeof value !== "string" && value.length) {
        const lengths = value.map((a) => a?.length || 0);
        content = value[lengths.indexOf(Math.max(...lengths))]?.toString() || "";
    }
    else {
        let valueStr = value !== null && value !== undefined ? `${value}` : "";
        content = valueStr.length > 15 ? `${valueStr.slice(0, 15)}...` : valueStr.toString();
    }
    const onValueUpdate = (newValue) => {
        if (Array.isArray(newValue)) {
            setUpdated([...newValue]);
        }
        else if (typeof newValue === "object") {
            setUpdated({ ...newValue });
        }
        else
            setUpdated(newValue);
        onUpdate(newValue);
    };
    return ((0, jsx_runtime_1.jsxs)(DesignUI_1.ValueEditorWrapper, { onClick: () => (navigate ? navigate("Select") : undefined), className: "ValueEditor-root", content: content, children: [mode === "display_mode" ? ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: react_1.default.createElement(displayRenderUI, {
                    value: updated,
                    forData,
                }) })) : null, mode === "edit_mode" && forData.type !== DataTypes_1.DataTypes.OBJECT ? ((0, jsx_runtime_1.jsx)(DesignUI_1.EditModeValueEditorRender, { content: content, className: "XValueEditor-editWrapper", children: react_1.default.createElement(editRenderUI, {
                    value: updated,
                    forData,
                    onUpdate: onValueUpdate,
                    editMode: editMode || "inline",
                    ref,
                }) })) : null, mode === "display_mode_edit" || (forData.type === DataTypes_1.DataTypes.OBJECT && mode === "edit_mode") ? ((0, jsx_runtime_1.jsx)(exports.DisplayEditModeValueEditorRender, { value: updated, forData: forData, onUpdate: onValueUpdate, mode: mode, editMode: editMode || "inline", displayRenderUI: displayRenderUI, editRenderUI: editRenderUI, ref: ref })) : null] }));
});
exports.DisplayEditModeValueEditorRender = react_1.default.forwardRef(({ value, forData, onUpdate, editMode, editRenderUI, displayRenderUI }, ref) => {
    const [mode, setMode] = (0, react_1.useState)("display_mode");
    const [updated, setUpdated] = (0, react_1.useState)(value);
    const [anchorEl, setAnchorEl] = (0, react_1.useState)(null);
    const onValueUpdate = (newValue) => {
        if (Array.isArray(newValue)) {
            setUpdated([...newValue]);
        }
        else {
            setUpdated(newValue);
        }
        if (editMode === "inline") {
            onUpdate(newValue);
        }
    };
    (0, react_1.useEffect)(() => {
        if (Array.isArray(value)) {
            setUpdated([...value]);
        }
        else if (typeof value === "object") {
            setUpdated({ ...value });
        }
        else {
            setUpdated(value);
        }
    }, [value, setUpdated]);
    const onClear = (event) => {
        event.stopPropagation();
        onUpdate(undefined);
    };
    const onDone = (event) => {
        event.stopPropagation();
        onUpdate(updated);
        setMode("display_mode");
        setAnchorEl(null);
    };
    if (editMode === "inline" && forData.type !== DataTypes_1.DataTypes.OBJECT) {
        let content;
        if (Array.isArray(updated) && typeof updated !== "string") {
            const lengths = value.map((a) => a?.length || 0);
            content = updated[lengths.indexOf(Math.max(...lengths))].toString();
        }
        else {
            content = (updated || "").toString();
        }
        return ((0, jsx_runtime_1.jsx)(DesignUI_1.DisplayEditModeRender, { onClick: () => setMode("edit_mode"), "data-testid": "ValueEditor-DisplayEdit-Inline", children: mode === "display_mode" ? ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: react_1.default.createElement(displayRenderUI, {
                    value,
                    forData,
                }) })) : ((0, jsx_runtime_1.jsx)(core_1.ClickAwayListener, { onClickAway: () => setMode("display_mode"), children: (0, jsx_runtime_1.jsx)(DesignUI_1.EditModeValueEditorRender, { content: content, children: react_1.default.createElement(editRenderUI, {
                        value: updated,
                        forData,
                        editMode: "inline",
                        onUpdate: onValueUpdate,
                        ref,
                    }) }) })) }));
    }
    return ((0, jsx_runtime_1.jsxs)(DesignUI_1.DisplayEditModeRender, { onClick: (event) => {
            setMode("edit_mode");
            setAnchorEl(event.currentTarget);
        }, "data-testid": "ValueEditor-DisplayEdit-Layer", children: [displayRenderUI({ value, forData }), forData.type !== DataTypes_1.DataTypes.OBJECT ? ((0, jsx_runtime_1.jsxs)(DesignUI_1.EditLayerWrapper, { open: !!anchorEl, anchorEl: anchorEl, onClose: () => {
                    setAnchorEl(null);
                    setMode("display_mode");
                }, children: [react_1.default.createElement(editRenderUI, {
                        value: updated,
                        forData,
                        editMode: "inline",
                        onUpdate: onValueUpdate,
                        ref,
                    }), (0, jsx_runtime_1.jsx)(ButtonGroupRender, { children: (0, jsx_runtime_1.jsx)(StyledButton_1.StyledButton, { color: "primary", variant: "contained", onClick: onDone, "data-testid": "XValueEditor-done", children: "Done" }) })] })) : ((0, jsx_runtime_1.jsx)(UILayer_1.UILayer, { open: !!anchorEl, onClose: () => {
                    setAnchorEl(null);
                    setMode("display_mode");
                }, maxWidth: false, padding: "16px 20px", renderUI: () => ((0, jsx_runtime_1.jsxs)(LayerRender, { children: [react_1.default.createElement(editRenderUI, {
                            value: updated,
                            forData,
                            editMode: "inline",
                            onUpdate: onValueUpdate,
                            ref,
                        }), (0, jsx_runtime_1.jsxs)(ButtonGroupRender, { children: [(0, jsx_runtime_1.jsx)(Link_1.StyledLink, { onClick: onClear, children: "Clear" }), (0, jsx_runtime_1.jsx)(StyledButton_1.StyledButton, { color: "primary", variant: "contained", onClick: onDone, children: "Done" })] })] })) }))] }));
});
const ButtonGroupRender = styled_components_1.default.div `
    display: flex;
    justify-content: space-between;
    align-items: center;

    padding: 15px 0 10px;
`;
const LayerRender = styled_components_1.default.div `
    display: flex;
    flex-direction: column;
    overflow: hidden;

    .ValueEditor-display {
        flex: 1;
        overflow: auto;
    }
`;
//# sourceMappingURL=DataEditing.js.map