function _array_like_to_array(arr, len) {
    if (len == null || len > arr.length) len = arr.length;
    for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
    return arr2;
}
function _array_with_holes(arr) {
    if (Array.isArray(arr)) return arr;
}
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 _iterable_to_array_limit(arr, i) {
    var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
    if (_i == null) return;
    var _arr = [];
    var _n = true;
    var _d = false;
    var _s, _e;
    try {
        for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
            _arr.push(_s.value);
            if (i && _arr.length === i) break;
        }
    } catch (err) {
        _d = true;
        _e = err;
    } finally{
        try {
            if (!_n && _i["return"] != null) _i["return"]();
        } finally{
            if (_d) throw _e;
        }
    }
    return _arr;
}
function _non_iterable_rest() {
    throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _object_spread(target) {
    for(var i = 1; i < arguments.length; i++){
        var source = arguments[i] != null ? arguments[i] : {};
        var ownKeys = Object.keys(source);
        if (typeof Object.getOwnPropertySymbols === "function") {
            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 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 = source != null ? source : {};
    if (Object.getOwnPropertyDescriptors) {
        Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
    } else {
        ownKeys(Object(source)).forEach(function(key) {
            Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
        });
    }
    return target;
}
function _sliced_to_array(arr, i) {
    return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
}
function _unsupported_iterable_to_array(o, minLen) {
    if (!o) return;
    if (typeof o === "string") return _array_like_to_array(o, minLen);
    var n = Object.prototype.toString.call(o).slice(8, -1);
    if (n === "Object" && o.constructor) n = o.constructor.name;
    if (n === "Map" || n === "Set") return Array.from(n);
    if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
}
import { FileMarkdown, FileXml, ArrowLeft as LeftIcon, SquareTerminal } from "@sofa-design/icons";
import { ConfigProvider, Empty, Segmented, Spin } from "antd";
import classNames from "classnames";
import React, { useContext, useEffect, useRef, useState } from "react";
import useAutoScroll from "../../Hooks/useAutoScroll";
import { I18nContext } from "../../I18n";
import { MarkdownEditor } from "../../MarkdownEditor";
import { parserMdToSchema } from "../../MarkdownEditor/editor/parser/parserMdToSchema";
import { HtmlPreview } from "../HtmlPreview";
import { useRealtimeFollowStyle } from "./style";
var SCROLL_TOLERANCE = 30;
var SCROLL_TIMEOUT = 100;
var SCROLL_DELAY = 50;
var TYPE_CONFIGS = {
    shell: {
        icon: SquareTerminal,
        titleKey: 'workspace.terminalExecution',
        defaultTitle: '终端执行'
    },
    html: {
        icon: FileXml,
        titleKey: 'workspace.createHtmlFile',
        defaultTitle: '创建 HTML 文件'
    },
    markdown: {
        icon: FileMarkdown,
        titleKey: 'workspace.markdownContent',
        defaultTitle: 'Markdown 内容'
    },
    md: {
        icon: FileMarkdown,
        titleKey: 'workspace.markdownContent',
        defaultTitle: 'Markdown 内容'
    },
    default: {
        icon: SquareTerminal,
        titleKey: 'workspace.terminalExecution',
        defaultTitle: '终端执行'
    }
};
var ICON_TYPE_CLASSES = {
    html: 'html',
    markdown: 'md',
    md: 'md'
};
var getTypeConfig = function(type, locale) {
    var config = TYPE_CONFIGS[type];
    return {
        icon: config.icon,
        title: (locale === null || locale === void 0 ? void 0 : locale[config.titleKey]) || config.defaultTitle
    };
};
var getIconTypeClass = function(type, prefixCls) {
    var suffix = ICON_TYPE_CLASSES[type] || 'default';
    return "".concat(prefixCls, "-header-icon--").concat(suffix);
};
var isTestEnvironment = function() {
    return process.env.NODE_ENV === 'test';
};
var renderNode = function(node) {
    return typeof node === 'function' ? node() : node;
};
var RealtimeHeader = function(param) {
    var data = param.data, hasBorder = param.hasBorder, prefixCls = param.prefixCls, hashId = param.hashId;
    var getPrefixCls = useContext(ConfigProvider.ConfigContext).getPrefixCls;
    var locale = useContext(I18nContext).locale;
    var finalPrefixCls = prefixCls || getPrefixCls('workspace-realtime');
    var config = getTypeConfig(data.type, locale);
    var IconComponent = data.icon || config.icon;
    var headerTitle = data.title || config.title;
    var headerSubTitle = data.subTitle;
    var hasBackButton = Boolean(data.onBack);
    var iconNode = /*#__PURE__*/ React.createElement("div", {
        className: classNames("".concat(finalPrefixCls, "-header-icon"), getIconTypeClass(data.type, finalPrefixCls), hashId)
    }, /*#__PURE__*/ React.createElement(IconComponent, null));
    var _obj;
    return /*#__PURE__*/ React.createElement("header", {
        className: classNames("".concat(finalPrefixCls, "-header"), (_obj = {}, _define_property(_obj, "".concat(finalPrefixCls, "-header-with-border"), hasBorder), _define_property(_obj, "".concat(finalPrefixCls, "-header-with-back"), hasBackButton), _obj), hashId)
    }, /*#__PURE__*/ React.createElement("div", {
        className: classNames("".concat(finalPrefixCls, "-header-left"), hashId)
    }, hasBackButton && /*#__PURE__*/ React.createElement("button", {
        type: "button",
        className: classNames("".concat(finalPrefixCls, "-header-back-button"), hashId),
        onClick: data.onBack
    }, /*#__PURE__*/ React.createElement(LeftIcon, {
        className: classNames("".concat(finalPrefixCls, "-header-back-icon"), hashId)
    })), /*#__PURE__*/ React.createElement("div", {
        className: classNames("".concat(finalPrefixCls, "-header-content"), hashId)
    }, !hasBackButton && iconNode, /*#__PURE__*/ React.createElement("div", {
        className: classNames("".concat(finalPrefixCls, "-header-title-wrapper"), hashId)
    }, /*#__PURE__*/ React.createElement("div", {
        className: classNames("".concat(finalPrefixCls, "-header-title"), hashId)
    }, hasBackButton && iconNode, headerTitle), headerSubTitle && /*#__PURE__*/ React.createElement("div", {
        className: classNames("".concat(finalPrefixCls, "-header-subtitle"), hashId),
        title: headerSubTitle
    }, headerSubTitle)))), /*#__PURE__*/ React.createElement("div", {
        className: classNames("".concat(finalPrefixCls, "-header-right"), hashId)
    }, data.rightContent));
};
var BASE_EDITOR_CONFIG = {
    readonly: true,
    toc: false,
    style: {
        width: '100%'
    },
    typewriter: true
};
var SHELL_CODE_PROPS = {
    theme: 'chaos',
    showGutter: true,
    showLineNumbers: true,
    hideToolBar: true
};
var VISIBLE_OVERFLOW_STYLE = {
    overflow: 'visible'
};
var EDITOR_CONFIGS = {
    shell: _object_spread_props(_object_spread({}, BASE_EDITOR_CONFIG), {
        contentStyle: _object_spread({
            padding: 0
        }, VISIBLE_OVERFLOW_STYLE),
        codeProps: SHELL_CODE_PROPS
    }),
    markdown: _object_spread_props(_object_spread({}, BASE_EDITOR_CONFIG), {
        contentStyle: _object_spread({
            padding: 16
        }, VISIBLE_OVERFLOW_STYLE),
        height: '100%'
    })
};
var getEditorConfig = function(type) {
    if (type === 'md') return EDITOR_CONFIGS.markdown;
    return EDITOR_CONFIGS[type] || BASE_EDITOR_CONFIG;
};
var Overlay = function(param) {
    var status = param.status, loadingRender = param.loadingRender, errorRender = param.errorRender, prefixCls = param.prefixCls, hashId = param.hashId;
    var getPrefixCls = useContext(ConfigProvider.ConfigContext).getPrefixCls;
    var locale = useContext(I18nContext).locale;
    var finalPrefixCls = prefixCls || getPrefixCls('workspace-realtime');
    if (status !== 'loading' && status !== 'error') return null;
    var loadingNode = renderNode(loadingRender);
    var errorNode = renderNode(errorRender);
    var content = status === 'loading' ? loadingNode || /*#__PURE__*/ React.createElement(Spin, null) : errorNode || /*#__PURE__*/ React.createElement("span", null, (locale === null || locale === void 0 ? void 0 : locale['htmlPreview.renderFailed']) || '页面渲染失败');
    var _obj;
    return /*#__PURE__*/ React.createElement("div", {
        className: classNames("".concat(finalPrefixCls, "-overlay"), (_obj = {}, _define_property(_obj, "".concat(finalPrefixCls, "-overlay--loading"), status === 'loading'), _define_property(_obj, "".concat(finalPrefixCls, "-overlay--error"), status === 'error'), _obj), hashId)
    }, content);
};
var getContentForEditor = function(type, content) {
    if (type === 'html') {
        var html = typeof content === 'string' ? content : '';
        return "```html\n".concat(html, "\n```");
    }
    return String(content);
};
var shouldUpdateEditor = function(type, htmlViewMode) {
    if (type === 'shell') return true;
    if (type === 'markdown' || type === 'md') return true;
    if (type === 'html' && htmlViewMode === 'code') return true;
    return false;
};
/**
 * RealtimeFollow 组件
 *
 * 实时跟随显示，支持 HTML、Markdown、Shell 等类型
 *
 * @example
 * ```tsx
 * <RealtimeFollow data={{ type: 'shell', content: '$ ls' }} />
 * ```
 */ export var RealtimeFollow = function(param) {
    var data = param.data, _param_htmlViewMode = param.htmlViewMode, htmlViewMode = _param_htmlViewMode === void 0 ? 'preview' : _param_htmlViewMode, prefixCls = param.prefixCls, hashId = param.hashId;
    var _data_typewriter, _data_content;
    var _data_markdownEditorProps;
    var getPrefixCls = useContext(ConfigProvider.ConfigContext).getPrefixCls;
    var finalPrefixCls = prefixCls || getPrefixCls('workspace-realtime');
    var mdInstance = useRef();
    var isTestEnv = isTestEnvironment();
    var _useAutoScroll = useAutoScroll({
        SCROLL_TOLERANCE: SCROLL_TOLERANCE,
        timeout: SCROLL_TIMEOUT,
        deps: [
            isTestEnv
        ]
    }), autoScrollRef = _useAutoScroll.containerRef, scrollToBottom = _useAutoScroll.scrollToBottom;
    useEffect(function() {
        var _mdInstance_current;
        if (isTestEnv || !((_mdInstance_current = mdInstance.current) === null || _mdInstance_current === void 0 ? void 0 : _mdInstance_current.store)) return;
        if (!shouldUpdateEditor(data.type, htmlViewMode)) return;
        var content = getContentForEditor(data.type, data.content);
        var schema = parserMdToSchema(content, mdInstance.current.store.plugins).schema;
        mdInstance.current.store.updateNodeList(schema);
        if (data.typewriter && !isTestEnv) {
            setTimeout(function() {
                return scrollToBottom();
            }, SCROLL_DELAY);
        }
    }, [
        data.content,
        data.type,
        htmlViewMode,
        isTestEnv,
        data.typewriter,
        scrollToBottom
    ]);
    if (data.customContent) {
        var customNode = renderNode(data.customContent);
        return /*#__PURE__*/ React.createElement("div", {
            className: classNames("".concat(finalPrefixCls, "-content"), hashId)
        }, customNode || null);
    }
    if (data.type === 'html') {
        var html = typeof data.content === 'string' ? data.content : '';
        return /*#__PURE__*/ React.createElement("div", {
            className: classNames("".concat(finalPrefixCls, "-content"), hashId)
        }, /*#__PURE__*/ React.createElement(HtmlPreview, {
            html: html,
            status: isTestEnv ? 'done' : data.status,
            viewMode: htmlViewMode,
            onViewModeChange: function(m) {
                var _data_onViewModeChange;
                return (_data_onViewModeChange = data.onViewModeChange) === null || _data_onViewModeChange === void 0 ? void 0 : _data_onViewModeChange.call(data, m);
            },
            markdownEditorProps: data.markdownEditorProps,
            iframeProps: data.iframeProps,
            labels: data.labels,
            loadingRender: isTestEnv ? undefined : data.loadingRender,
            errorRender: isTestEnv ? undefined : data.errorRender,
            showSegmented: false,
            emptyRender: isTestEnv ? undefined : data.emptyRender
        }));
    }
    if (![
        'shell',
        'markdown',
        'md',
        'default'
    ].includes(data.type)) {
        return null;
    }
    var defaultProps = getEditorConfig(data.type);
    var mergedProps = _object_spread_props(_object_spread({}, defaultProps, data.markdownEditorProps), {
        typewriter: isTestEnv ? false : (_data_typewriter = data.typewriter) !== null && _data_typewriter !== void 0 ? _data_typewriter : defaultProps.typewriter,
        style: _object_spread({
            maxHeight: 'auto'
        }, defaultProps.style, (_data_markdownEditorProps = data.markdownEditorProps) === null || _data_markdownEditorProps === void 0 ? void 0 : _data_markdownEditorProps.style)
    });
    var contentStr = String((_data_content = data.content) !== null && _data_content !== void 0 ? _data_content : '');
    var isEmpty = contentStr.trim() === '';
    var shouldShowEmpty = !isTestEnv && isEmpty && data.status !== 'loading' && data.status !== 'error';
    var emptyNode = renderNode(data.emptyRender);
    return /*#__PURE__*/ React.createElement("div", {
        className: classNames("".concat(finalPrefixCls, "-content"), hashId),
        ref: isTestEnv ? undefined : autoScrollRef
    }, !isTestEnv && /*#__PURE__*/ React.createElement(Overlay, {
        status: data.status,
        loadingRender: data.loadingRender,
        errorRender: data.errorRender,
        prefixCls: prefixCls,
        hashId: hashId
    }), shouldShowEmpty ? /*#__PURE__*/ React.createElement("div", {
        className: classNames("".concat(finalPrefixCls, "-empty"), hashId)
    }, emptyNode || /*#__PURE__*/ React.createElement(Empty, null)) : /*#__PURE__*/ React.createElement(MarkdownEditor, _object_spread_props(_object_spread({}, mergedProps), {
        editorRef: mdInstance,
        initValue: String(data.content)
    })));
};
var getSegmentedOptions = function(labels) {
    return [
        {
            label: /*#__PURE__*/ React.createElement("div", {
                className: "ant-segmented-item-title"
            }, labels.preview),
            value: 'preview'
        },
        {
            label: /*#__PURE__*/ React.createElement("div", {
                className: "ant-segmented-item-title"
            }, labels.code),
            value: 'code'
        }
    ];
};
var getRightContent = function(data, labels, htmlViewMode, handleSetMode, prefixCls, hashId) {
    if (data.rightContent) return data.rightContent;
    if (data.type !== 'html') return null;
    var segmentedNode = data.segmentedItems && data.segmentedItems.length > 0 ? /*#__PURE__*/ React.createElement(Segmented, {
        options: data.segmentedItems,
        onChange: function(val) {
            var _data_onViewModeChange;
            return (_data_onViewModeChange = data.onViewModeChange) === null || _data_onViewModeChange === void 0 ? void 0 : _data_onViewModeChange.call(data, String(val));
        }
    }) : /*#__PURE__*/ React.createElement(Segmented, {
        options: getSegmentedOptions(labels),
        value: htmlViewMode,
        onChange: function(val) {
            return handleSetMode(val);
        }
    });
    if (!data.segmentedExtra) return segmentedNode;
    return /*#__PURE__*/ React.createElement("div", {
        className: classNames("".concat(prefixCls, "-header-segmented-right"), hashId)
    }, segmentedNode, /*#__PURE__*/ React.createElement("div", {
        className: classNames("".concat(prefixCls, "-header-segmented-right-extra"), hashId)
    }, data.segmentedExtra));
};
/**
 * RealtimeFollowList 组件
 *
 * RealtimeFollow 的包装组件，管理视图模式状态
 */ export var RealtimeFollowList = function(param) {
    var data = param.data;
    var _data_labels, _data_labels1;
    var isControlled = data.type === 'html' && data.viewMode !== undefined;
    var _useState = _sliced_to_array(useState(data.defaultViewMode || 'preview'), 2), innerViewMode = _useState[0], setInnerViewMode = _useState[1];
    var htmlViewMode = data.type === 'html' ? isControlled ? data.viewMode : innerViewMode : 'preview';
    var handleSetMode = function(mode) {
        var _data_onViewModeChange;
        if (!isControlled) setInnerViewMode(mode);
        (_data_onViewModeChange = data.onViewModeChange) === null || _data_onViewModeChange === void 0 ? void 0 : _data_onViewModeChange.call(data, mode);
    };
    var locale = useContext(I18nContext).locale;
    var labels = {
        preview: ((_data_labels = data.labels) === null || _data_labels === void 0 ? void 0 : _data_labels.preview) || (locale === null || locale === void 0 ? void 0 : locale['htmlPreview.preview']) || '预览',
        code: ((_data_labels1 = data.labels) === null || _data_labels1 === void 0 ? void 0 : _data_labels1.code) || (locale === null || locale === void 0 ? void 0 : locale['htmlPreview.code']) || '代码'
    };
    var getPrefixCls = useContext(ConfigProvider.ConfigContext).getPrefixCls;
    var prefixCls = getPrefixCls('workspace-realtime');
    var styleResult = useRealtimeFollowStyle(prefixCls);
    var _ref = styleResult || {
        wrapSSR: function(node) {
            return node;
        },
        hashId: ''
    }, wrapSSR = _ref.wrapSSR, hashId = _ref.hashId;
    var rightContent = getRightContent(data, labels, htmlViewMode, handleSetMode, prefixCls, hashId);
    var headerData = _object_spread_props(_object_spread({}, data), {
        rightContent: rightContent
    });
    var hasBorder = data.type === 'html' || data.type === 'markdown';
    return wrapSSR(/*#__PURE__*/ React.createElement("div", {
        className: classNames("".concat(prefixCls, "-container"), "".concat(prefixCls, "--").concat(data.type), data.className, hashId),
        style: data.style,
        "data-testid": "realtime-follow"
    }, /*#__PURE__*/ React.createElement(RealtimeHeader, {
        data: headerData,
        hasBorder: hasBorder,
        prefixCls: prefixCls,
        hashId: hashId
    }), /*#__PURE__*/ React.createElement(RealtimeFollow, {
        data: data,
        htmlViewMode: htmlViewMode,
        prefixCls: prefixCls,
        hashId: hashId
    })));
};
