import ComponentLoader from "../ComponentLoader/ComponentLoader";
import ErrorMessage from "../ErrorMessage/ErrorMessage";
import BasicForm from "../Forms/BasicForm";
import FormFieldSchemaType from "../Forms/Types/FormFieldSchemaType";
import ComponentValuePickerModal from "./ComponentValuePickerModal";
import ModelFieldPicker from "./ModelFieldPicker";
import { componentInputTypeToFormFieldType } from "./Utils";
import VariableModal from "./VariableModal";
import { ComponentInputType, } from "../../../Types/Workflow/Component";
import { LIMIT_PER_PROJECT } from "../../../Types/Database/LimitMax";
import ModelAPI from "../../Utils/ModelAPI/ModelAPI";
import Workflow from "../../../Models/DatabaseModels/Workflow";
import React, { useEffect, useRef, useState, } from "react";
const ArgumentsForm = (props) => {
    var _a;
    const formRef = useRef(null);
    const [component, setComponent] = useState(props.component);
    const [showVariableModal, setShowVariableModal] = useState(false);
    const [showComponentPickerModal, setShowComponentPickerModal] = useState(false);
    const [hasFormValidationErrors, setHasFormValidationErrors] = useState({});
    const [selectedArgId, setSelectedArgId] = useState("");
    /*
     * Workflows in the current project, used to populate dropdowns for any
     * argument of type WorkflowSelect (e.g. the "Workflow" field on the
     * Execute Workflow component). Empty until the fetch completes.
     */
    const [workflowDropdownOptions, setWorkflowDropdownOptions] = useState([]);
    const [isLoadingWorkflows, setIsLoadingWorkflows] = useState(false);
    const hasWorkflowSelectArg = Boolean((_a = component.metadata.arguments) === null || _a === void 0 ? void 0 : _a.some((arg) => {
        return arg.type === ComponentInputType.WorkflowSelect;
    }));
    useEffect(() => {
        if (!hasWorkflowSelectArg) {
            return;
        }
        let cancelled = false;
        setIsLoadingWorkflows(true);
        const loadWorkflows = async () => {
            try {
                const result = await ModelAPI.getList({
                    modelType: Workflow,
                    query: {},
                    limit: LIMIT_PER_PROJECT,
                    skip: 0,
                    select: {
                        _id: true,
                        name: true,
                    },
                    sort: {
                        name: "Ascending",
                    },
                });
                if (cancelled) {
                    return;
                }
                const currentWorkflowIdStr = props.workflowId.toString();
                const options = result.data
                    .filter((wf) => {
                    var _a;
                    // Exclude the current workflow — can't pick yourself.
                    return ((_a = wf._id) === null || _a === void 0 ? void 0 : _a.toString()) !== currentWorkflowIdStr;
                })
                    .map((wf) => {
                    var _a, _b, _c, _d;
                    return {
                        label: wf.name || ((_b = (_a = wf._id) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : ""),
                        value: (_d = (_c = wf._id) === null || _c === void 0 ? void 0 : _c.toString()) !== null && _d !== void 0 ? _d : "",
                    };
                });
                setWorkflowDropdownOptions(options);
            }
            catch (_a) {
                /*
                 * Swallow: the dropdown will simply be empty and the user can try
                 * again by re-opening the settings panel.
                 */
                if (!cancelled) {
                    setWorkflowDropdownOptions([]);
                }
            }
            finally {
                if (!cancelled) {
                    setIsLoadingWorkflows(false);
                }
            }
        };
        void loadWorkflows();
        return () => {
            cancelled = true;
        };
        // Only re-fetch when the component in the settings panel changes identity.
    }, [component.id, hasWorkflowSelectArg]);
    useEffect(() => {
        props.onHasFormValidationErrors(hasFormValidationErrors);
    }, [hasFormValidationErrors]);
    useEffect(() => {
        props.onFormChange(component);
    }, [component]);
    return (React.createElement("div", null,
        React.createElement("div", null,
            component.metadata.arguments &&
                component.metadata.arguments.length === 0 && (React.createElement(ErrorMessage, { message: "This step does not need any settings." })),
            hasWorkflowSelectArg && isLoadingWorkflows && React.createElement(ComponentLoader, null),
            component.metadata.arguments &&
                component.metadata.arguments.length > 0 &&
                !(hasWorkflowSelectArg && isLoadingWorkflows) && (React.createElement(BasicForm, { hideSubmitButton: true, ref: formRef, initialValues: Object.assign({}, (component.arguments || {})), onChange: (values) => {
                    setComponent(Object.assign(Object.assign({}, component), { arguments: Object.assign(Object.assign({}, (component.arguments || {})), (values || {})) }));
                }, onFormValidationErrorChanged: (hasError) => {
                    if (hasFormValidationErrors["id"] !== hasError) {
                        setHasFormValidationErrors(Object.assign(Object.assign({}, hasFormValidationErrors), { id: hasError }));
                    }
                }, fields: component.metadata.arguments &&
                    component.metadata.arguments.map((arg) => {
                        const isWorkflowSelect = arg.type === ComponentInputType.WorkflowSelect;
                        /*
                         * Database Select args (the "Select Fields" / "Listen on"
                         * trigger inputs) get a tree-style field picker backed by
                         * the model's schema, instead of a raw JSON textarea. We
                         * need a tableName on the component metadata to fetch the
                         * column list; without it, fall back to the JSON editor.
                         */
                        const useFieldPicker = arg.type === ComponentInputType.Select &&
                            Boolean(component.metadata.tableName);
                        const baseField = useFieldPicker
                            ? {
                                fieldType: FormFieldSchemaType.CustomComponent,
                                getCustomElement: (_values, customProps) => {
                                    return (React.createElement(ModelFieldPicker, { tableName: component.metadata.tableName, initialValue: customProps.initialValue, onChange: (value) => {
                                            var _a;
                                            void ((_a = customProps.onChange) === null || _a === void 0 ? void 0 : _a.call(customProps, value));
                                        }, placeholder: customProps.placeholder, error: customProps.error, tabIndex: customProps.tabIndex }));
                                },
                            }
                            : componentInputTypeToFormFieldType(arg.type, component.arguments && component.arguments[arg.id]
                                ? component.arguments[arg.id]
                                : null);
                        /*
                         * For WorkflowSelect, inject the dynamically fetched list
                         * of workflows as dropdown options.
                         */
                        if (isWorkflowSelect) {
                            baseField.dropdownOptions = workflowDropdownOptions;
                        }
                        /*
                         * The "pick from component / variable" footer doesn't
                         * apply to the field picker (it edits a structured object,
                         * not a free-text expression) or to WorkflowSelect.
                         */
                        const showVariableFooter = !isWorkflowSelect && !useFieldPicker;
                        return Object.assign({ title: `${arg.name}`, footerElement: showVariableFooter ? (React.createElement("div", { className: "text-gray-500" },
                                React.createElement("p", { className: "text-sm" },
                                    "Pick this value from other",
                                    " ",
                                    React.createElement("button", { className: "underline text-blue-500 hover:text-blue-600 cursor-pointer", onClick: () => {
                                            setSelectedArgId(arg.id);
                                            setShowComponentPickerModal(true);
                                        } }, "component"),
                                    " ",
                                    "or from",
                                    " ",
                                    React.createElement("button", { className: "underline text-blue-500 hover:text-blue-600 cursor-pointer", onClick: () => {
                                            setSelectedArgId(arg.id);
                                            setShowVariableModal(true);
                                        } }, "variable.")))) : undefined, description: `${arg.required ? "Required" : "Optional"}. ${arg.description}`, field: {
                                [arg.id]: true,
                            }, required: arg.required, placeholder: arg.placeholder }, baseField);
                    }) }))),
        showVariableModal && (React.createElement(VariableModal, { workflowId: props.workflowId, onClose: () => {
                setShowVariableModal(false);
            }, onSave: (variableId) => {
                var _a;
                setShowVariableModal(false);
                (_a = formRef.current) === null || _a === void 0 ? void 0 : _a.setFieldValue(selectedArgId, (component.arguments && component.arguments[selectedArgId]
                    ? component.arguments[selectedArgId]
                    : "") + variableId);
            } })),
        showComponentPickerModal && (React.createElement(ComponentValuePickerModal, { components: props.graphComponents, onClose: () => {
                setShowComponentPickerModal(false);
            }, onSave: (returnValuePath) => {
                var _a;
                setShowComponentPickerModal(false);
                (_a = formRef.current) === null || _a === void 0 ? void 0 : _a.setFieldValue(selectedArgId, (component.arguments && component.arguments[selectedArgId]
                    ? component.arguments[selectedArgId]
                    : "") + returnValuePath);
            } }))));
};
export default ArgumentsForm;
//# sourceMappingURL=ArgumentsForm.js.map