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 _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 { useCallback, useEffect, useRef, useState } from "react";
import { INITIAL_FENCE_STATE, updateFenceStateForLine } from "./streaming/fenceTracker";
/**
 * 流式 token 缓存类型。
 * 在流式场景中，部分 Markdown token（link、image、table 等）可能处于未闭合状态，
 * 直接交给 parser 会产生错误结果。此 hook 将已完成的内容和未完成的 pending 分离，
 * 仅将已完成的部分交给 parser。
 *
 * 移植自 @ant-design/x-markdown 的 useStreaming hook。
 */ export var StreamCacheTokenType = /*#__PURE__*/ function(StreamCacheTokenType) {
    StreamCacheTokenType["Text"] = "text";
    StreamCacheTokenType["Link"] = "link";
    StreamCacheTokenType["Image"] = "image";
    StreamCacheTokenType["Html"] = "html";
    StreamCacheTokenType["Emphasis"] = "emphasis";
    StreamCacheTokenType["List"] = "list";
    StreamCacheTokenType["Table"] = "table";
    StreamCacheTokenType["InlineCode"] = "inline-code";
    return StreamCacheTokenType;
}({});
var STREAM_INCOMPLETE_REGEX = {
    image: [
        /^!\[[^\]\r\n]{0,1000}$/,
        /^!\[[^\r\n]{0,1000}\]\(*[^)\r\n]{0,1000}$/
    ],
    link: [
        /^\[(?!\^)[^\]\r\n]{0,1000}$/,
        /^\[(?!\^)[^\r\n]{0,1000}\]\(+[^)\r\n]{0,1000}$/
    ],
    html: [
        /^<\/$/,
        /^<\/?[a-zA-Z][a-zA-Z0-9-]{0,100}[^>\r\n]{0,1000}$/
    ],
    commonEmphasis: [
        /^(\*{1,3}|_{1,3})(?!\s)(?!.*\1$)[^\r\n]{0,1000}$/
    ],
    list: [
        /^[-+*]\s{0,3}$/,
        /^[-+*]\s{1,3}(\*{1,3}|_{1,3})(?!\s)(?!.*\1$)[^\r\n]{0,1000}$/
    ],
    'inline-code': [
        /^`[^`\r\n]{0,300}$/,
        /^`{2,}$/
    ]
};
var STREAMING_LOADING_PLACEHOLDER = '...';
var parsePipeRowCells = function parsePipeRowCells(line) {
    var trimmedLine = line.trim();
    if (!trimmedLine.startsWith('|') || !trimmedLine.endsWith('|')) {
        return null;
    }
    var cells = trimmedLine.split('|').slice(1, -1).map(function(cell) {
        return cell.trim();
    });
    if (!cells.length) return null;
    return cells;
};
var isTableSeparatorCell = function isTableSeparatorCell(cell) {
    return /^:?-{3,}:?$/.test(cell);
};
/**
 * 判断表格是否仍不完整。
 * 等待 header + separator + 第一行数据完整闭合后提交。
 */ var isTableIncomplete = function isTableIncomplete(markdown) {
    var _firstDataRowTrimmed_match;
    if (markdown.includes('\n\n')) return false;
    var lines = markdown.replace(/\r\n/g, '\n').split('\n');
    // 需要至少 3 行：header | separator | 第一行数据
    if (lines.length < 3) return true;
    var _lines = _sliced_to_array(lines, 3), header = _lines[0], separator = _lines[1], firstDataRow = _lines[2];
    var headerCells = parsePipeRowCells(header);
    if (!headerCells) return false;
    var separatorCells = parsePipeRowCells(separator);
    if (!separatorCells || separatorCells.length !== headerCells.length) {
        return false;
    }
    var isSeparatorValid = separatorCells.every(isTableSeparatorCell);
    if (!isSeparatorValid) return false;
    var firstDataRowTrimmed = (firstDataRow === null || firstDataRow === void 0 ? void 0 : firstDataRow.trim()) || '';
    // 第三行仍为空，说明首行数据尚未到达，继续缓存避免提前渲染 table header
    if (!firstDataRowTrimmed) return true;
    // 第三行不是表格行，视为当前表格 token 已完成（例如 header-only 表格后接普通文本）
    if (!firstDataRowTrimmed.startsWith('|')) return false;
    var minPipeDelimiterCount = headerCells.length + 1;
    var currentPipeDelimiterCount = ((_firstDataRowTrimmed_match = firstDataRowTrimmed.match(/\|/g)) === null || _firstDataRowTrimmed_match === void 0 ? void 0 : _firstDataRowTrimmed_match.length) || 0;
    // 管道分隔符数量不足，说明第一行数据还未输入完整
    if (currentPipeDelimiterCount < minPipeDelimiterCount) return true;
    // 第一行数据必须是闭合的管道行（以 | 结尾），否则继续缓存
    if (!firstDataRowTrimmed.endsWith('|')) return true;
    var firstDataRowCells = parsePipeRowCells(firstDataRow);
    if (!firstDataRowCells || firstDataRowCells.length !== headerCells.length) {
        return true;
    }
    return false;
};
var _obj;
var tokenRecognizerMap = (_obj = {}, _define_property(_obj, "link", {
    tokenType: "link",
    isStartOfToken: function isStartOfToken(md) {
        return md.startsWith('[');
    },
    isStreamingValid: function isStreamingValid(md) {
        return STREAM_INCOMPLETE_REGEX.link.some(function(re) {
            return re.test(md);
        });
    }
}), _define_property(_obj, "image", {
    tokenType: "image",
    isStartOfToken: function isStartOfToken(md) {
        return md.startsWith('!');
    },
    isStreamingValid: function isStreamingValid(md) {
        return STREAM_INCOMPLETE_REGEX.image.some(function(re) {
            return re.test(md);
        });
    }
}), _define_property(_obj, "html", {
    tokenType: "html",
    isStartOfToken: function isStartOfToken(md) {
        return md.startsWith('<');
    },
    isStreamingValid: function isStreamingValid(md) {
        return STREAM_INCOMPLETE_REGEX.html.some(function(re) {
            return re.test(md);
        });
    }
}), _define_property(_obj, "emphasis", {
    tokenType: "emphasis",
    isStartOfToken: function isStartOfToken(md) {
        return md.startsWith('*') || md.startsWith('_');
    },
    isStreamingValid: function isStreamingValid(md) {
        return STREAM_INCOMPLETE_REGEX.commonEmphasis.some(function(re) {
            return re.test(md);
        });
    }
}), _define_property(_obj, "list", {
    tokenType: "list",
    isStartOfToken: function isStartOfToken(md) {
        return /^[-+*]/.test(md);
    },
    isStreamingValid: function isStreamingValid(md) {
        return STREAM_INCOMPLETE_REGEX.list.some(function(re) {
            return re.test(md);
        });
    },
    getCommitPrefix: function getCommitPrefix(pending) {
        var _pending_match;
        var listPrefix = (_pending_match = pending.match(/^([-+*]\s{0,3})/)) === null || _pending_match === void 0 ? void 0 : _pending_match[1];
        var rest = listPrefix ? pending.slice(listPrefix.length) : '';
        return listPrefix && rest.startsWith('`') ? listPrefix : null;
    }
}), _define_property(_obj, "table", {
    tokenType: "table",
    isStartOfToken: function isStartOfToken(md) {
        return md.startsWith('|');
    },
    isStreamingValid: isTableIncomplete
}), _define_property(_obj, "inline-code", {
    tokenType: "inline-code",
    isStartOfToken: function isStartOfToken(md) {
        return md.startsWith('`');
    },
    isStreamingValid: function isStreamingValid(md) {
        return STREAM_INCOMPLETE_REGEX['inline-code'].some(function(re) {
            return re.test(md);
        });
    }
}), _obj);
var commitCache = function commitCache(cache) {
    if (cache.pending) {
        cache.completeMarkdown += cache.pending;
        cache.pending = '';
    }
    cache.token = "text";
};
var recognize = function recognize(cache, tokenType) {
    var recognizer = tokenRecognizerMap[tokenType];
    if (!recognizer) return;
    var token = cache.token, pending = cache.pending;
    if (token === "text" && recognizer.isStartOfToken(pending)) {
        cache.token = tokenType;
        return;
    }
    if (token === tokenType && !recognizer.isStreamingValid(pending)) {
        var _recognizer_getCommitPrefix;
        var prefix = (_recognizer_getCommitPrefix = recognizer.getCommitPrefix) === null || _recognizer_getCommitPrefix === void 0 ? void 0 : _recognizer_getCommitPrefix.call(recognizer, pending);
        if (prefix) {
            cache.completeMarkdown += prefix;
            cache.pending = pending.slice(prefix.length);
            cache.token = "text";
            return;
        }
        commitCache(cache);
    }
};
var recognizeHandlers = Object.values(tokenRecognizerMap).map(function(rec) {
    return {
        tokenType: rec.tokenType,
        recognize: function recognize1(cache) {
            return recognize(cache, rec.tokenType);
        }
    };
});
var getInitialCache = function getInitialCache() {
    return {
        pending: '',
        token: "text",
        processedLength: 0,
        completeMarkdown: '',
        fenceState: _object_spread({}, INITIAL_FENCE_STATE),
        currentLine: ''
    };
};
var getStreamingOutput = function getStreamingOutput(cache) {
    if (cache.completeMarkdown) return cache.completeMarkdown;
    if (cache.pending) return STREAMING_LOADING_PLACEHOLDER;
    return '';
};
/** 流式 token 缓存——暂缓不完整的 link/image/table 等，避免 parser 错误解析 */ export var useStreaming = function useStreaming(input, enabled) {
    var _useState = _sliced_to_array(useState(''), 2), output = _useState[0], setOutput = _useState[1];
    var cacheRef = useRef(getInitialCache());
    var processStreaming = useCallback(function(text) {
        if (!text) {
            setOutput('');
            cacheRef.current = getInitialCache();
            return;
        }
        var expectedPrefix = cacheRef.current.completeMarkdown + cacheRef.current.pending;
        if (!text.startsWith(expectedPrefix)) {
            cacheRef.current = getInitialCache();
        }
        var cache = cacheRef.current;
        var chunk = text.slice(cache.processedLength);
        if (!chunk) return;
        // 非前缀重置后重建围栏状态（全量兜底，仅此处 O(n)）
        if (cache.processedLength === 0 && text.length > 0) {
            var existingText = cache.completeMarkdown + cache.pending;
            if (existingText.length === 0) {
                cache.fenceState = _object_spread({}, INITIAL_FENCE_STATE);
                cache.currentLine = '';
            }
        }
        cache.processedLength += chunk.length;
        var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
        try {
            for(var _iterator = chunk[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
                var char = _step.value;
                cache.pending += char;
                if (char === '\n') {
                    var prevInFenced = cache.fenceState.inFenced;
                    cache.fenceState = updateFenceStateForLine(cache.fenceState, cache.currentLine);
                    cache.currentLine = '';
                    if (cache.fenceState.inFenced) {
                        continue;
                    }
                    if (prevInFenced && !cache.fenceState.inFenced) {
                        commitCache(cache);
                        continue;
                    }
                } else {
                    cache.currentLine += char;
                    if (cache.fenceState.inFenced) {
                        continue;
                    }
                }
                if (cache.token === "text") {
                    var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
                    try {
                        for(var _iterator1 = recognizeHandlers[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
                            var handler = _step1.value;
                            handler.recognize(cache);
                        }
                    } catch (err) {
                        _didIteratorError1 = true;
                        _iteratorError1 = err;
                    } finally{
                        try {
                            if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
                                _iterator1.return();
                            }
                        } finally{
                            if (_didIteratorError1) {
                                throw _iteratorError1;
                            }
                        }
                    }
                } else {
                    var handler1 = recognizeHandlers.find(function(h) {
                        return h.tokenType === cache.token;
                    });
                    handler1 === null || handler1 === void 0 ? void 0 : handler1.recognize(cache);
                    if (cache.token === "text") {
                        var _iteratorNormalCompletion2 = true, _didIteratorError2 = false, _iteratorError2 = undefined;
                        try {
                            for(var _iterator2 = recognizeHandlers[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true){
                                var h = _step2.value;
                                h.recognize(cache);
                            }
                        } catch (err) {
                            _didIteratorError2 = true;
                            _iteratorError2 = err;
                        } finally{
                            try {
                                if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
                                    _iterator2.return();
                                }
                            } finally{
                                if (_didIteratorError2) {
                                    throw _iteratorError2;
                                }
                            }
                        }
                    }
                }
                if (cache.token === "text") {
                    commitCache(cache);
                }
            }
        } catch (err) {
            _didIteratorError = true;
            _iteratorError = err;
        } finally{
            try {
                if (!_iteratorNormalCompletion && _iterator.return != null) {
                    _iterator.return();
                }
            } finally{
                if (_didIteratorError) {
                    throw _iteratorError;
                }
            }
        }
        setOutput(getStreamingOutput(cache));
    }, []);
    useEffect(function() {
        if (typeof input !== 'string') {
            setOutput('');
            cacheRef.current = getInitialCache();
            return;
        }
        if (!enabled) {
            setOutput(input);
            cacheRef.current = getInitialCache();
            return;
        }
        processStreaming(input);
    }, [
        input,
        enabled,
        processStreaming
    ]);
    return output;
};
