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 { memo, useEffect, useRef, useState } from 'react';
import { useDeep } from './client.js';
import { gql } from '@apollo/client/index.js';
import React from 'react';
export class CatchErrors extends React.Component {
    constructor(props) {
        super(props);
        this.errorRenderer = (error, reset) => React.createElement(React.Fragment, null);
        this.state = { error: undefined };
        this.reset = () => {
            var _a, _b;
            this.setState({ error: undefined });
            ((_a = this === null || this === void 0 ? void 0 : this.props) === null || _a === void 0 ? void 0 : _a.reset) && ((_b = this === null || this === void 0 ? void 0 : this.props) === null || _b === void 0 ? void 0 : _b.reset());
        };
    }
    static getDerivedStateFromError(error) {
        console.log('getDerivedStateFromError', error);
        return { error };
    }
    componentDidCatch(error, errorInfo) {
        console.log('componentDidCatch', error, errorInfo);
    }
    componentDidMounted() {
        var _a, _b;
        ((_a = this === null || this === void 0 ? void 0 : this.props) === null || _a === void 0 ? void 0 : _a.onMounted) && ((_b = this === null || this === void 0 ? void 0 : this.props) === null || _b === void 0 ? void 0 : _b.onMounted((error) => this.setState({ error: error })));
    }
    render() {
        var _a, _b;
        const error = this.props.error || this.state.error;
        if (error) {
            return ((_a = this === null || this === void 0 ? void 0 : this.props) === null || _a === void 0 ? void 0 : _a.errorRenderer) ? (_b = this === null || this === void 0 ? void 0 : this.props) === null || _b === void 0 ? void 0 : _b.errorRenderer(error, this.reset) : this === null || this === void 0 ? void 0 : this.errorRenderer(error, this.reset);
        }
        return this.props.children;
    }
}
export function evalClientHandler(options) {
    return __awaiter(this, void 0, void 0, function* () {
        const { value, deep, input = {}, } = options;
        try {
            console.log('evalClientHandler', 'value', value);
            const evalResult = eval(value);
            if (typeof evalResult === 'function') {
                return {
                    data: yield evalResult(Object.assign({ deep, gql }, input)),
                };
            }
            else {
                return {
                    error: new Error(`Client handler must return a function, got ${typeof evalResult}`),
                };
            }
        }
        catch (error) {
            console.log('evalClientHandler', 'error', error);
            return { error };
        }
        return {};
    });
}
export const ClientHandler = memo(function ClientHandler(_props) {
    var _a;
    const { linkId, handlerId, context = [], ml, onClose, fillSize, error: outerError, ErrorComponent } = _props, props = __rest(_props, ["linkId", "handlerId", "context", "ml", "onClose", "fillSize", "error", "ErrorComponent"]);
    const deep = useDeep();
    const _ml = ml || (deep === null || deep === void 0 ? void 0 : deep.minilinks);
    const hid = useFindClientHandler(_props);
    const [file] = deep.useMinilinksQuery({
        id: (hid === null || hid === void 0 ? void 0 : hid.dist_id) || 0,
    });
    const [{ Component, errored } = {}, setState] = useState({ Component: undefined, errored: undefined });
    const lastEvalRef = useRef(0);
    useEffect(() => {
        var _a;
        if (!hid)
            return;
        const value = (_a = file === null || file === void 0 ? void 0 : file.value) === null || _a === void 0 ? void 0 : _a.value;
        if (!value) {
            return;
        }
        const evalId = ++lastEvalRef.current;
        evalClientHandler({ value, deep }).then(({ data, error }) => {
            if (evalId === lastEvalRef.current) {
                console.log('ClientHandler evalClientHandler setState', { file, data, error });
                if (!error) {
                    setState(() => ({ Component: data }));
                    (erroredResetRef === null || erroredResetRef === void 0 ? void 0 : erroredResetRef.current) && (erroredResetRef === null || erroredResetRef === void 0 ? void 0 : erroredResetRef.current(), erroredResetRef.current = undefined);
                }
                else {
                    setErrorRef.current && setErrorRef.current(error);
                    setState({ Component: undefined, errored: error });
                }
            }
            else {
                console.log('ClientHandler evalClientHandler outdated', { file, data, error, evalId, 'lastEvalRef.current': lastEvalRef.current });
            }
        });
    }, [(_a = file === null || file === void 0 ? void 0 : file.value) === null || _a === void 0 ? void 0 : _a.value, hid]);
    const erroredResetRef = useRef();
    const setErrorRef = useRef();
    return (React.createElement(React.Fragment, null,
        React.createElement(CatchErrors, { error: errored || outerError, errorRenderer: (error, reset) => {
                erroredResetRef.current = reset;
                return React.createElement(ErrorComponent, { error: error, reset: reset });
            }, onMounted: (setError) => setErrorRef.current = setError }, (typeof (Component) === 'function') ? React.createElement(React.Fragment, null, [React.createElement(ClientHandlerRenderer, Object.assign({ key: Component.toString(), Component: Component }, props, { fillSize: fillSize, link: _ml.byId[linkId], ml: _ml, onClose: onClose }))]) : React.createElement(React.Fragment, null))));
});
;
export const ClientHandlerRenderer = React.memo(function ClientHandlerRenderer(_a) {
    var { Component, fillSize = false, onClose } = _a, props = __rest(_a, ["Component", "fillSize", "onClose"]);
    return React.createElement(React.Fragment, null, typeof (Component) === 'function' && React.createElement(Component, Object.assign({ onClose: onClose, fillSize: fillSize }, props, { style: Object.assign(Object.assign({}, (fillSize ? { width: '100%', height: '100%' } : {})), props === null || props === void 0 ? void 0 : props.style) })));
});
export function useFindClientHandler(_a) {
    var { linkId, handlerId, context = [], ml, onClose, fillSize } = _a, props = __rest(_a, ["linkId", "handlerId", "context", "ml", "onClose", "fillSize"]);
    const deep = useDeep();
    const [hid, setHid] = useState();
    useEffect(() => {
        (() => __awaiter(this, void 0, void 0, function* () {
            if (hid)
                return;
            const handler = yield deep._findHandler({ context, handlerId });
            if (handler)
                setHid(handler);
        }))();
    }, [context, handlerId, hid]);
    return hid;
}
//# sourceMappingURL=client-handler.js.map