"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
Object.defineProperty(exports, "default", {
    enumerable: true,
    get: function() {
        return _default;
    }
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _jsxruntime = require("react/jsx-runtime");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const _bus = /*#__PURE__*/ _interop_require_wildcard._(require("./bus"));
const _ShadowPortal = require("../internal/components/ShadowPortal");
const _BuildError = require("../internal/container/BuildError");
const _Errors = require("../internal/container/Errors");
const _ErrorBoundary = require("./ErrorBoundary");
const _Base = require("../internal/styles/Base");
const _ComponentStyles = require("../internal/styles/ComponentStyles");
const _CssReset = require("../internal/styles/CssReset");
function pushErrorFilterDuplicates(errors, err) {
    return [
        ...errors.filter((e)=>{
            // Filter out duplicate errors
            return e.event.reason !== err.event.reason;
        }),
        err
    ];
}
function reducer(state, ev) {
    switch(ev.type){
        case _bus.TYPE_BUILD_OK:
            {
                return {
                    ...state,
                    buildError: null
                };
            }
        case _bus.TYPE_BUILD_ERROR:
            {
                return {
                    ...state,
                    buildError: ev.message
                };
            }
        case _bus.TYPE_BEFORE_REFRESH:
            {
                return {
                    ...state,
                    refreshState: {
                        type: "pending",
                        errors: []
                    }
                };
            }
        case _bus.TYPE_REFRESH:
            {
                return {
                    ...state,
                    buildError: null,
                    errors: // Errors can come in during updates. In this case, UNHANDLED_ERROR
                    // and UNHANDLED_REJECTION events might be dispatched between the
                    // BEFORE_REFRESH and the REFRESH event. We want to keep those errors
                    // around until the next refresh. Otherwise we run into a race
                    // condition where those errors would be cleared on refresh completion
                    // before they can be displayed.
                    state.refreshState.type === "pending" ? state.refreshState.errors : [],
                    refreshState: {
                        type: "idle"
                    }
                };
            }
        case _bus.TYPE_UNHANDLED_ERROR:
        case _bus.TYPE_UNHANDLED_REJECTION:
            {
                switch(state.refreshState.type){
                    case "idle":
                        {
                            return {
                                ...state,
                                nextId: state.nextId + 1,
                                errors: pushErrorFilterDuplicates(state.errors, {
                                    id: state.nextId,
                                    event: ev
                                })
                            };
                        }
                    case "pending":
                        {
                            return {
                                ...state,
                                nextId: state.nextId + 1,
                                refreshState: {
                                    ...state.refreshState,
                                    errors: pushErrorFilterDuplicates(state.refreshState.errors, {
                                        id: state.nextId,
                                        event: ev
                                    })
                                }
                            };
                        }
                    default:
                        // eslint-disable-next-line @typescript-eslint/no-unused-vars
                        const _ = state.refreshState;
                        return state;
                }
            }
        default:
            {
                // eslint-disable-next-line @typescript-eslint/no-unused-vars
                const _ = ev;
                return state;
            }
    }
}
const shouldPreventDisplay = (errorType, preventType)=>{
    if (!preventType || !errorType) {
        return false;
    }
    return preventType.includes(errorType);
};
const ReactDevOverlay = function ReactDevOverlay(param) {
    let { children, preventDisplay, globalOverlay } = param;
    const [state, dispatch] = _react.useReducer(reducer, {
        nextId: 1,
        buildError: null,
        errors: [],
        refreshState: {
            type: "idle"
        }
    });
    _react.useEffect(()=>{
        _bus.on(dispatch);
        return function() {
            _bus.off(dispatch);
        };
    }, [
        dispatch
    ]);
    const onComponentError = _react.useCallback((_error, _componentStack)=>{
    // TODO: special handling
    }, []);
    const hasBuildError = state.buildError != null;
    const hasRuntimeErrors = Boolean(state.errors.length);
    const errorType = hasBuildError ? "build" : hasRuntimeErrors ? "runtime" : null;
    const isMounted = errorType !== null;
    const displayPrevented = shouldPreventDisplay(errorType, preventDisplay);
    return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_react.Fragment, {
        children: [
            /*#__PURE__*/ (0, _jsxruntime.jsx)(_ErrorBoundary.ErrorBoundary, {
                globalOverlay: globalOverlay,
                isMounted: isMounted,
                onError: onComponentError,
                children: children != null ? children : null
            }),
            isMounted ? /*#__PURE__*/ (0, _jsxruntime.jsxs)(_ShadowPortal.ShadowPortal, {
                children: [
                    /*#__PURE__*/ (0, _jsxruntime.jsx)(_CssReset.CssReset, {}),
                    /*#__PURE__*/ (0, _jsxruntime.jsx)(_Base.Base, {}),
                    /*#__PURE__*/ (0, _jsxruntime.jsx)(_ComponentStyles.ComponentStyles, {}),
                    displayPrevented ? null : hasBuildError ? /*#__PURE__*/ (0, _jsxruntime.jsx)(_BuildError.BuildError, {
                        message: state.buildError
                    }) : hasRuntimeErrors ? /*#__PURE__*/ (0, _jsxruntime.jsx)(_Errors.Errors, {
                        isAppDir: false,
                        errors: state.errors,
                        initialDisplayState: "fullscreen"
                    }) : undefined
                ]
            }) : undefined
        ]
    });
};
const _default = ReactDevOverlay;

if ((typeof exports.default === 'function' || (typeof exports.default === 'object' && exports.default !== null)) && typeof exports.default.__esModule === 'undefined') {
  Object.defineProperty(exports.default, '__esModule', { value: true });
  Object.assign(exports.default, exports);
  module.exports = exports.default;
}

//# sourceMappingURL=ReactDevOverlay.js.map