import ansiHTML from "./utils/ansiHTML.js";
function _define_property(obj, key, value) {
    if (key in obj) Object.defineProperty(obj, key, {
        value: value,
        enumerable: true,
        configurable: true,
        writable: true
    });
    else obj[key] = value;
    return obj;
}
function _object_spread(target) {
    for(var i = 1; i < arguments.length; i++){
        var source = null != arguments[i] ? arguments[i] : {};
        var ownKeys = Object.keys(source);
        if ("function" == typeof Object.getOwnPropertySymbols) ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
            return Object.getOwnPropertyDescriptor(source, sym).enumerable;
        }));
        ownKeys.forEach(function(key) {
            _define_property(target, key, source[key]);
        });
    }
    return target;
}
function overlay_ownKeys(object, enumerableOnly) {
    var keys = Object.keys(object);
    if (Object.getOwnPropertySymbols) {
        var symbols = Object.getOwnPropertySymbols(object);
        if (enumerableOnly) symbols = symbols.filter(function(sym) {
            return Object.getOwnPropertyDescriptor(object, sym).enumerable;
        });
        keys.push.apply(keys, symbols);
    }
    return keys;
}
function _object_spread_props(target, source) {
    source = null != source ? source : {};
    if (Object.getOwnPropertyDescriptors) Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
    else overlay_ownKeys(Object(source)).forEach(function(key) {
        Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
    });
    return target;
}
const getCodePoint = String.prototype.codePointAt ? (input, position)=>input.codePointAt(position) : (input, position)=>(input.charCodeAt(position) - 0xd800) * 0x400 + input.charCodeAt(position + 1) - 0xdc00 + 0x10000;
const replaceUsingRegExp = (macroText, macroRegExp, macroReplacer)=>{
    macroRegExp.lastIndex = 0;
    let replaceMatch = macroRegExp.exec(macroText);
    let replaceResult;
    if (replaceMatch) {
        replaceResult = '';
        let replaceLastIndex = 0;
        do {
            if (replaceLastIndex !== replaceMatch.index) replaceResult += macroText.slice(replaceLastIndex, replaceMatch.index);
            const replaceInput = replaceMatch[0];
            replaceResult += macroReplacer(replaceInput);
            replaceLastIndex = replaceMatch.index + replaceInput.length;
        }while (replaceMatch = macroRegExp.exec(macroText));
        if (replaceLastIndex !== macroText.length) replaceResult += macroText.slice(replaceLastIndex);
    } else replaceResult = macroText;
    return replaceResult;
};
const references = {
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&apos;',
    '&': '&amp;'
};
function encode(text) {
    if (!text) return '';
    return replaceUsingRegExp(text, /[<>'"&]/g, (input)=>{
        let result = references[input];
        if (!result) {
            const code = input.length > 1 ? getCodePoint(input, 0) : input.charCodeAt(0);
            result = `&#${code};`;
        }
        return result;
    });
}
function createMachine({ states, context, initial }, { actions }) {
    let currentState = initial;
    let currentContext = context;
    return {
        send: (event)=>{
            const currentStateOn = states[currentState].on;
            const transitionConfig = currentStateOn && currentStateOn[event.type];
            if (transitionConfig) {
                currentState = transitionConfig.target;
                if (transitionConfig.actions) transitionConfig.actions.forEach((actName)=>{
                    const actionImpl = actions[actName];
                    const nextContextValue = actionImpl && actionImpl(currentContext, event);
                    if (nextContextValue) currentContext = _object_spread({}, currentContext, nextContextValue);
                });
            }
        }
    };
}
const createOverlayMachine = (options)=>{
    const { hideOverlay, showOverlay } = options;
    return createMachine({
        initial: 'hidden',
        context: {
            level: 'error',
            messages: [],
            messageSource: 'build'
        },
        states: {
            hidden: {
                on: {
                    BUILD_ERROR: {
                        target: 'displayBuildError',
                        actions: [
                            'setMessages',
                            'showOverlay'
                        ]
                    },
                    RUNTIME_ERROR: {
                        target: 'displayRuntimeError',
                        actions: [
                            'setMessages',
                            'showOverlay'
                        ]
                    }
                }
            },
            displayBuildError: {
                on: {
                    DISMISS: {
                        target: 'hidden',
                        actions: [
                            'dismissMessages',
                            'hideOverlay'
                        ]
                    },
                    BUILD_ERROR: {
                        target: 'displayBuildError',
                        actions: [
                            'appendMessages',
                            'showOverlay'
                        ]
                    }
                }
            },
            displayRuntimeError: {
                on: {
                    DISMISS: {
                        target: 'hidden',
                        actions: [
                            'dismissMessages',
                            'hideOverlay'
                        ]
                    },
                    RUNTIME_ERROR: {
                        target: 'displayRuntimeError',
                        actions: [
                            'appendMessages',
                            'showOverlay'
                        ]
                    },
                    BUILD_ERROR: {
                        target: 'displayBuildError',
                        actions: [
                            'setMessages',
                            'showOverlay'
                        ]
                    }
                }
            }
        }
    }, {
        actions: {
            dismissMessages: ()=>({
                    messages: [],
                    level: 'error',
                    messageSource: 'build'
                }),
            appendMessages: (context, event)=>({
                    messages: context.messages.concat(event.messages),
                    level: event.level || context.level,
                    messageSource: 'RUNTIME_ERROR' === event.type ? 'runtime' : 'build'
                }),
            setMessages: (context, event)=>({
                    messages: event.messages,
                    level: event.level || context.level,
                    messageSource: 'RUNTIME_ERROR' === event.type ? 'runtime' : 'build'
                }),
            hideOverlay,
            showOverlay
        }
    });
};
const parseErrorToStacks = (error)=>{
    if (!error || !(error instanceof Error)) throw new Error('parseErrorToStacks expects Error object');
    if ('string' == typeof error.stack) return error.stack.split('\n').filter((stack)=>stack !== `Error: ${error.message}`);
};
const listenToRuntimeError = (callback)=>{
    window.addEventListener('error', callback);
    return function() {
        window.removeEventListener('error', callback);
    };
};
const listenToUnhandledRejection = (callback)=>{
    window.addEventListener('unhandledrejection', callback);
    return function() {
        window.removeEventListener('unhandledrejection', callback);
    };
};
const msgStyles = {
    error: {
        backgroundColor: 'rgba(206, 17, 38, 0.1)',
        color: '#fccfcf'
    },
    warning: {
        backgroundColor: 'rgba(251, 245, 180, 0.1)',
        color: '#fbf5b4'
    }
};
const iframeStyle = {
    position: 'fixed',
    top: '0px',
    left: '0px',
    right: '0px',
    bottom: '0px',
    width: '100vw',
    height: '100vh',
    border: 'none',
    'z-index': 9999999999
};
const containerStyle = {
    position: 'fixed',
    boxSizing: 'border-box',
    left: '0px',
    top: '0px',
    right: '0px',
    bottom: '0px',
    width: '100vw',
    height: '100vh',
    fontSize: 'large',
    padding: '2rem 2rem 4rem 2rem',
    lineHeight: '1.2',
    whiteSpace: 'pre-wrap',
    overflow: 'auto',
    backgroundColor: 'rgba(0, 0, 0, 0.9)',
    color: 'white'
};
const headerStyle = {
    color: '#e83b46',
    fontSize: '2em',
    whiteSpace: 'pre-wrap',
    fontFamily: 'sans-serif',
    margin: '0 2rem 2rem 0',
    flex: '0 0 auto',
    maxHeight: '50%',
    overflow: 'auto'
};
const dismissButtonStyle = {
    color: '#ffffff',
    lineHeight: '1rem',
    fontSize: '1.5rem',
    padding: '1rem',
    cursor: 'pointer',
    position: 'absolute',
    right: '0px',
    top: '0px',
    backgroundColor: 'transparent',
    border: 'none'
};
const msgTypeStyle = {
    color: '#e83b46',
    fontSize: '1.2em',
    marginBottom: '1rem',
    fontFamily: 'sans-serif'
};
const msgTextStyle = {
    lineHeight: '1.5',
    fontSize: '1rem',
    fontFamily: 'Menlo, Consolas, monospace'
};
const colors = {
    reset: [
        'transparent',
        'transparent'
    ],
    black: '181818',
    red: 'E36049',
    green: 'B3CB74',
    yellow: 'FFD080',
    blue: '7CAFC2',
    magenta: '7FACCA',
    cyan: 'C3C2EF',
    lightgrey: 'EBE7E3',
    darkgrey: '6D7891'
};
ansiHTML.setColors(colors);
const formatProblem = (type, item)=>{
    let header = 'warning' === type ? 'WARNING' : 'ERROR';
    let body = '';
    if ('string' == typeof item) body += item;
    else {
        const file = item.file || '';
        const moduleName = item.moduleName ? -1 !== item.moduleName.indexOf('!') ? `${item.moduleName.replace(/^(\s|\S)*!/, '')} (${item.moduleName})` : `${item.moduleName}` : '';
        const loc = item.loc;
        header += `${moduleName || file ? ` in ${moduleName ? `${moduleName}${file ? ` (${file})` : ''}` : file}${loc ? ` ${loc}` : ''}` : ''}`;
        body += item.message || '';
    }
    if ('string' != typeof item && Array.isArray(item.stack)) item.stack.forEach((stack)=>{
        if ('string' == typeof stack) body += `\r\n${stack}`;
    });
    return {
        header,
        body
    };
};
const createOverlay = (options)=>{
    let iframeContainerElement;
    let containerElement;
    let headerElement;
    let onLoadQueue = [];
    let overlayTrustedTypesPolicy;
    function applyStyle(element, style) {
        Object.keys(style).forEach((prop)=>{
            element.style[prop] = style[prop];
        });
    }
    function createContainer(trustedTypesPolicyName) {
        if (window.trustedTypes) overlayTrustedTypesPolicy = window.trustedTypes.createPolicy(trustedTypesPolicyName || 'rspack-dev-server#overlay', {
            createHTML: (value)=>value
        });
        iframeContainerElement = document.createElement('iframe');
        iframeContainerElement.id = 'rspack-dev-server-client-overlay';
        iframeContainerElement.src = 'about:blank';
        applyStyle(iframeContainerElement, iframeStyle);
        iframeContainerElement.onload = ()=>{
            const contentElement = (null == iframeContainerElement ? void 0 : iframeContainerElement.contentDocument).createElement('div');
            containerElement = (null == iframeContainerElement ? void 0 : iframeContainerElement.contentDocument).createElement('div');
            contentElement.id = 'rspack-dev-server-client-overlay-div';
            applyStyle(contentElement, containerStyle);
            headerElement = document.createElement('div');
            headerElement.innerText = 'Compiled with problems:';
            applyStyle(headerElement, headerStyle);
            const closeButtonElement = document.createElement('button');
            applyStyle(closeButtonElement, dismissButtonStyle);
            closeButtonElement.innerText = '×';
            closeButtonElement.ariaLabel = 'Dismiss';
            closeButtonElement.addEventListener('click', ()=>{
                overlayService.send({
                    type: 'DISMISS'
                });
            });
            contentElement.appendChild(headerElement);
            contentElement.appendChild(closeButtonElement);
            contentElement.appendChild(containerElement);
            (null == iframeContainerElement ? void 0 : iframeContainerElement.contentDocument).body.appendChild(contentElement);
            onLoadQueue.forEach((onLoad)=>{
                onLoad(contentElement);
            });
            onLoadQueue = [];
            iframeContainerElement.onload = null;
        };
        document.body.appendChild(iframeContainerElement);
    }
    function ensureOverlayExists(callback, trustedTypesPolicyName) {
        if (containerElement) {
            containerElement.innerHTML = overlayTrustedTypesPolicy ? overlayTrustedTypesPolicy.createHTML('') : '';
            callback(containerElement);
            return;
        }
        onLoadQueue.push(callback);
        if (iframeContainerElement) return;
        createContainer(trustedTypesPolicyName);
    }
    function hide() {
        if (!iframeContainerElement) return;
        document.body.removeChild(iframeContainerElement);
        iframeContainerElement = null;
        containerElement = null;
    }
    function show(type, messages, trustedTypesPolicyName, messageSource) {
        ensureOverlayExists(()=>{
            headerElement.innerText = 'runtime' === messageSource ? 'Uncaught runtime errors:' : 'Compiled with problems:';
            messages.forEach((message)=>{
                const entryElement = document.createElement('div');
                const msgStyle = 'warning' === type ? msgStyles.warning : msgStyles.error;
                applyStyle(entryElement, _object_spread_props(_object_spread({}, msgStyle), {
                    padding: '1rem 1rem 1.5rem 1rem'
                }));
                const typeElement = document.createElement('div');
                const { header, body } = formatProblem(type, message);
                typeElement.innerText = header;
                applyStyle(typeElement, msgTypeStyle);
                if ('string' != typeof message && message.moduleIdentifier) {
                    applyStyle(typeElement, {
                        cursor: 'pointer'
                    });
                    typeElement.setAttribute('data-can-open', 'true');
                    typeElement.addEventListener('click', ()=>{
                        fetch(`/rspack-dev-server/open-editor?fileName=${message.moduleIdentifier}`);
                    });
                }
                const text = ansiHTML(encode(body));
                const messageTextNode = document.createElement('div');
                applyStyle(messageTextNode, msgTextStyle);
                messageTextNode.innerHTML = overlayTrustedTypesPolicy ? overlayTrustedTypesPolicy.createHTML(text) : text;
                entryElement.appendChild(typeElement);
                entryElement.appendChild(messageTextNode);
                null == containerElement || containerElement.appendChild(entryElement);
            });
        }, trustedTypesPolicyName);
    }
    let handleEscapeKey;
    const hideOverlayWithEscCleanup = ()=>{
        window.removeEventListener('keydown', handleEscapeKey);
        hide();
    };
    const overlayService = createOverlayMachine({
        showOverlay: ({ level = 'error', messages, messageSource })=>show(level, messages, options.trustedTypesPolicyName, messageSource),
        hideOverlay: hideOverlayWithEscCleanup
    });
    handleEscapeKey = (event)=>{
        if ('Escape' === event.key || 'Esc' === event.key || 27 === event.keyCode) overlayService.send({
            type: 'DISMISS'
        });
    };
    window.addEventListener('keydown', handleEscapeKey);
    if (options.catchRuntimeError) {
        const handleError = (error, fallbackMessage)=>{
            const errorObject = error instanceof Error ? error : new Error(error || fallbackMessage, {
                cause: error
            });
            const shouldDisplay = 'function' == typeof options.catchRuntimeError ? options.catchRuntimeError(errorObject) : true;
            if (shouldDisplay) overlayService.send({
                type: 'RUNTIME_ERROR',
                messages: [
                    {
                        message: errorObject.message,
                        stack: parseErrorToStacks(errorObject)
                    }
                ]
            });
        };
        listenToRuntimeError((errorEvent)=>{
            const { error, message } = errorEvent;
            if (!error && !message) return;
            if (error && error.stack && error.stack.includes('invokeGuardedCallbackDev')) return;
            handleError(error, message);
        });
        listenToUnhandledRejection((promiseRejectionEvent)=>{
            const { reason } = promiseRejectionEvent;
            handleError(reason, 'Unknown promise rejection reason');
        });
    }
    return overlayService;
};
export { createOverlay, formatProblem };
