import { jsx as _jsx } from "@emotion/react/jsx-runtime";
import React from "react";
import * as Sentry from "@sentry/react";
import { RuntimeContext } from "../RuntimeContext";
import format from "../utils/format";
import RuntimeComponentError from "../RuntimeComponentError";
import { useVariablesContext, useVariableValues } from "../VariablesContext";
import { Box } from "@chakra-ui/layout";
import EditorContext from "../EditorContext";
import useTemplate from "../hooks/useTemplate";
import { useActionTrigger } from "../hooks/useActionTrigger";
import { useRuntimeInput } from "../RuntimeInput";
import ListItemVariables from "../ListItemVariables";
import { useSourceHooks } from "../hooks/sourceHooks/useSourceHooks";
import iconsList from "../components/iconsList";
import { Spinner } from "@chakra-ui/react";
import qore from "../hooks/qore";
import { useTracking } from "react-tracking";
import EditModeWrapper from "./EditModeWrapper";
import ComponentWrapper from "./ComponentWrapper";
import { evaluateExpression } from "../utils/expressionParser";
import { useEvaluate } from "../hooks/useExpression";
import _ from "lodash";
import { useImportComponent } from "../builtinComponents";
export const hooks = {
    useTemplate,
    useEvaluate,
    format,
    useActionTrigger,
    useRuntimeInput,
    useClient: qore.useClient,
    useTracking,
    useVariableValues,
};
const components = {
    ListItemVariables,
    iconsList,
};
export default React.memo(function RuntimeComponent(props) {
    var _a, _b, _c;
    const { row, loading, error, revalidate, childrenMap } = props;
    const app = RuntimeContext.useSelectState((state) => state);
    const instance = RuntimeContext.useSelectState((state) => state.maps.component[props.component.component]);
    const instanceDef = useImportComponent(instance === null || instance === void 0 ? void 0 : instance.componentID);
    const activeComponent = EditorContext.useSelectState((state) => state.rightPanel.type === "component" ? state.rightPanel.id : "");
    const editMode = EditorContext.useSelectState((state) => state.editMode);
    const editorActions = EditorContext.useActions();
    const { values } = useVariablesContext();
    const variablesConfig = React.useMemo(() => Object.entries(values).map(([name, value]) => ({
        name,
        type: "any",
        evaluate: () => value,
    })), [values]);
    const shouldShow = React.useMemo(() => {
        if (!instance || instance.showCondition.conditions.length === 0)
            return true;
        const results = instance.showCondition.conditions.map((condition) => {
            const result = evaluateExpression(condition.formula, variablesConfig);
            return Boolean(result.type === "ok" && result.result);
        });
        return instance.showCondition.type === "all"
            ? results.every((result) => result)
            : results.some((result) => result);
    }, [instance, variablesConfig]);
    const user = qore.useCurrentUser();
    const instanceSource = React.useMemo(() => instance.source
        ? Object.assign(Object.assign({}, instance.source), { params: Object.fromEntries(Object.entries(instance.source.params).map(([key, val]) => [
                key,
                format((val !== null && val !== void 0 ? val : "").toString(), values),
            ])) }) : { type: "none", target: null, params: {} }, [instance.source, values]);
    const sourceHooks = useSourceHooks(instanceSource);
    const pageSourceHooks = useSourceHooks(props.source);
    const { data: componentSourceRecordData = {}, status: componentSourceRecordStatus, error: componentSourceRecordError, revalidate: componentSourceRecordRevalidate, } = sourceHooks.useFetch(instanceSource.params);
    const { data: componentSourceData = [], status: componentSourceStatus, error: componentSourceError, revalidate: componentSourceRevalidate, } = sourceHooks.useFetchList(instanceSource.params);
    const variables = React.useMemo(() => (instanceSource.type === "record" ? componentSourceRecordData : {}), [instanceSource.type, componentSourceRecordData]);
    const componentData = React.useMemo(() => ({
        user: user,
        page: { loading, error, row, revalidate },
        component: instanceSource.type === "list" ||
            (instanceSource.type === "record-list" &&
                instanceSource.sourceType === "list")
            ? {
                loading: componentSourceStatus === "loading",
                error: componentSourceError,
                rows: componentSourceData,
                revalidate: componentSourceRevalidate,
            }
            : instanceSource.type === "record" ||
                (instanceSource.type === "record-list" &&
                    instanceSource.sourceType === "record")
                ? {
                    loading: componentSourceRecordStatus === "loading",
                    error: componentSourceRecordError,
                    row: componentSourceRecordData,
                    revalidate: componentSourceRecordRevalidate,
                }
                : undefined,
    }), [
        user,
        loading,
        error,
        row,
        instanceSource.type,
        componentSourceStatus,
        componentSourceError,
        componentSourceData,
        componentSourceRecordStatus,
        componentSourceRecordError,
        componentSourceData,
    ]);
    const pageSource = React.useMemo(() => {
        var _a;
        return props.source.defaultRow.type === "first-row" && ((_a = componentData.page.row) === null || _a === void 0 ? void 0 : _a.id)
            ? Object.assign(Object.assign({}, props.source), { defaultRow: { type: "row-id", rowId: componentData.page.row.id } }) : props.source;
    }, [props.source, (_a = componentData.page.row) === null || _a === void 0 ? void 0 : _a.id]);
    const handleChangeActiveComponent = React.useCallback(() => {
        editorActions.setActiveComponent(props.component.component);
        editorActions.setRightPanel({
            type: "component",
            id: props.component.component,
        });
    }, [props.component.component]);
    const properties = React.useMemo(() => (Object.assign(Object.assign({}, instanceDef === null || instanceDef === void 0 ? void 0 : instanceDef.defaultProps), instance.properties)), [instanceDef === null || instanceDef === void 0 ? void 0 : instanceDef.defaultProps, instance.properties]);
    const componentHooks = React.useMemo(() => (Object.assign(Object.assign({}, hooks), { sourceHooks: {
            page: pageSourceHooks,
            component: sourceHooks,
        } })), [pageSourceHooks, sourceHooks]);
    const childrenList = React.useMemo(() => {
        if (!childrenMap)
            return [];
        return _.sortBy(childrenMap[props.component.component], ["metadata.idx"]);
    }, [childrenMap, props.component.component]);
    if (!instanceDef) {
        return (_jsx(Box, Object.assign({ display: "flex", justifyContent: "center" }, { children: _jsx(Spinner, {}) })));
    }
    if (!instanceDef || !shouldShow)
        return null;
    const RenderedComponent = (_jsx(ComponentWrapper, Object.assign({ display: (_b = instanceDef === null || instanceDef === void 0 ? void 0 : instanceDef.display) !== null && _b !== void 0 ? _b : "block", instance: instance }, { children: _jsx(ListItemVariables, Object.assign({ variables: variables }, { children: _jsx(instanceDef.Component, Object.assign({ app: app, instance: instance, 
                // @ts-ignore
                data: componentData, properties: properties, 
                // @ts-ignore
                source: instanceSource, pageSource: pageSource, hooks: componentHooks, components: components }, { children: childrenList.map((childInstance) => {
                    if (!childInstance) {
                        return null;
                    }
                    return (_jsx(RuntimeComponent, { row: props.row, source: pageSource, error: props.error, loading: props.loading, revalidate: props.revalidate, component: { component: childInstance.id }, childrenMap: childrenMap }, childInstance.id));
                }) })) })) })));
    const WithEditWrapper = editMode === "select" ? (_jsx(EditModeWrapper, Object.assign({ instance: instance, isActive: activeComponent === props.component.component, onClick: handleChangeActiveComponent, display: (_c = instanceDef === null || instanceDef === void 0 ? void 0 : instanceDef.display) !== null && _c !== void 0 ? _c : "block" }, { children: RenderedComponent }))) : (RenderedComponent);
    return (_jsx(Sentry.ErrorBoundary, Object.assign({ beforeCapture: (scope) => {
            scope.setContext("Component", {
                component: instance.componentID,
                properties,
            });
        }, fallback: () => _jsx(RuntimeComponentError, {}) }, { children: WithEditWrapper })));
});
//# sourceMappingURL=index.js.map