import { DEFAULT_COLLAPSED_CONTEXT_THRESHOLD, DEFAULT_EXPANDED_REGION, DEFAULT_RENDER_RANGE, DEFAULT_THEMES } from "../constants.js";
import { areLanguagesAttached } from "../highlighter/languages/areLanguagesAttached.js";
import { getHighlighterIfLoaded, getSharedHighlighter } from "../highlighter/shared_highlighter.js";
import { areThemesAttached } from "../highlighter/themes/areThemesAttached.js";
import { areRenderRangesEqual } from "../utils/areRenderRangesEqual.js";
import { areThemesEqual } from "../utils/areThemesEqual.js";
import { createGutterGap, createGutterItem, createGutterWrapper, createHastElement } from "../utils/hast_utils.js";
import { createAnnotationElement } from "../utils/createAnnotationElement.js";
import { createContentColumn } from "../utils/createContentColumn.js";
import { createFileHeaderElement } from "../utils/createFileHeaderElement.js";
import { createPreElement } from "../utils/createPreElement.js";
import { getFiletypeFromFileName } from "../utils/getFiletypeFromFileName.js";
import { getHighlighterOptions } from "../utils/getHighlighterOptions.js";
import { getLineAnnotationName } from "../utils/getLineAnnotationName.js";
import { createEmptyRowBuffer } from "../utils/createEmptyRowBuffer.js";
import { createNoNewlineElement } from "../utils/createNoNewlineElement.js";
import { createSeparator } from "../utils/createSeparator.js";
import { getHunkSeparatorSlotName } from "../utils/getHunkSeparatorSlotName.js";
import { getTotalLineCountFromHunks } from "../utils/getTotalLineCountFromHunks.js";
import { isDefaultRenderRange } from "../utils/isDefaultRenderRange.js";
import { iterateOverDiff } from "../utils/iterateOverDiff.js";
import { renderDiffWithHighlighter } from "../utils/renderDiffWithHighlighter.js";
import { toHtml } from "hast-util-to-html";

//#region src/renderers/DiffHunksRenderer.ts
let instanceId = -1;
var DiffHunksRenderer = class {
	__id = `diff-hunks-renderer:${++instanceId}`;
	highlighter;
	diff;
	expandedHunks = /* @__PURE__ */ new Map();
	deletionAnnotations = {};
	additionAnnotations = {};
	computedLang = "text";
	renderCache;
	constructor(options = { theme: DEFAULT_THEMES }, onRenderUpdate, workerManager) {
		this.options = options;
		this.onRenderUpdate = onRenderUpdate;
		this.workerManager = workerManager;
		if (workerManager?.isWorkingPool() !== true) this.highlighter = areThemesAttached(options.theme ?? DEFAULT_THEMES) ? getHighlighterIfLoaded() : void 0;
	}
	cleanUp() {
		this.highlighter = void 0;
		this.diff = void 0;
		this.renderCache = void 0;
		this.workerManager?.cleanUpPendingTasks(this);
		this.workerManager = void 0;
		this.onRenderUpdate = void 0;
	}
	recycle() {
		this.highlighter = void 0;
		this.diff = void 0;
		this.renderCache = void 0;
		this.workerManager?.cleanUpPendingTasks(this);
	}
	setOptions(options) {
		this.options = options;
	}
	mergeOptions(options) {
		this.options = {
			...this.options,
			...options
		};
	}
	setThemeType(themeType) {
		if (this.getOptionsWithDefaults().themeType === themeType) return;
		this.mergeOptions({ themeType });
	}
	expandHunk(index, direction) {
		const { expansionLineCount } = this.getOptionsWithDefaults();
		const region = { ...this.expandedHunks.get(index) ?? {
			fromStart: 0,
			fromEnd: 0
		} };
		if (direction === "up" || direction === "both") region.fromStart += expansionLineCount;
		if (direction === "down" || direction === "both") region.fromEnd += expansionLineCount;
		if (this.renderCache?.highlighted !== true) this.renderCache = void 0;
		this.expandedHunks.set(index, region);
	}
	getExpandedHunk(hunkIndex) {
		return this.expandedHunks.get(hunkIndex) ?? DEFAULT_EXPANDED_REGION;
	}
	getExpandedHunksMap() {
		return this.expandedHunks;
	}
	setLineAnnotations(lineAnnotations) {
		this.additionAnnotations = {};
		this.deletionAnnotations = {};
		for (const annotation of lineAnnotations) {
			const map = (() => {
				switch (annotation.side) {
					case "deletions": return this.deletionAnnotations;
					case "additions": return this.additionAnnotations;
				}
			})();
			const arr = map[annotation.lineNumber] ?? [];
			map[annotation.lineNumber] = arr;
			arr.push(annotation);
		}
	}
	getOptionsWithDefaults() {
		const { diffIndicators = "bars", diffStyle = "split", disableBackground = false, disableFileHeader = false, disableLineNumbers = false, disableVirtualizationBuffers = false, expandUnchanged = false, collapsedContextThreshold = DEFAULT_COLLAPSED_CONTEXT_THRESHOLD, expansionLineCount = 100, hunkSeparators = "line-info", lineDiffType = "word-alt", maxLineDiffLength = 1e3, overflow = "scroll", theme = DEFAULT_THEMES, themeType = "system", tokenizeMaxLineLength = 1e3, useCSSClasses = false } = this.options;
		return {
			diffIndicators,
			diffStyle,
			disableBackground,
			disableFileHeader,
			disableLineNumbers,
			disableVirtualizationBuffers,
			expandUnchanged,
			collapsedContextThreshold,
			expansionLineCount,
			hunkSeparators,
			lineDiffType,
			maxLineDiffLength,
			overflow,
			theme: this.workerManager?.getDiffRenderOptions().theme ?? theme,
			themeType,
			tokenizeMaxLineLength,
			useCSSClasses
		};
	}
	async initializeHighlighter() {
		this.highlighter = await getSharedHighlighter(getHighlighterOptions(this.computedLang, this.options));
		return this.highlighter;
	}
	hydrate(diff) {
		if (diff == null) return;
		this.diff = diff;
		const { options } = this.getRenderOptions(diff);
		let cache = this.workerManager?.getDiffResultCache(diff);
		if (cache != null && !areRenderOptionsEqual(options, cache.options)) cache = void 0;
		this.renderCache ??= {
			diff,
			highlighted: true,
			options,
			result: cache?.result,
			renderRange: void 0
		};
		if (this.workerManager?.isWorkingPool() === true && this.renderCache.result == null) this.workerManager.highlightDiffAST(this, this.diff);
		else this.asyncHighlight(diff).then(({ result, options: options$1 }) => {
			this.onHighlightSuccess(diff, result, options$1);
		});
	}
	getRenderOptions(diff) {
		const options = (() => {
			if (this.workerManager?.isWorkingPool() === true) return this.workerManager.getDiffRenderOptions();
			const { theme, tokenizeMaxLineLength, lineDiffType } = this.getOptionsWithDefaults();
			return {
				theme,
				tokenizeMaxLineLength,
				lineDiffType
			};
		})();
		this.getOptionsWithDefaults();
		const { renderCache } = this;
		if (renderCache?.result == null) return {
			options,
			forceRender: true
		};
		if (diff !== renderCache.diff || !areRenderOptionsEqual(options, renderCache.options)) return {
			options,
			forceRender: true
		};
		return {
			options,
			forceRender: false
		};
	}
	renderDiff(diff = this.renderCache?.diff, renderRange = DEFAULT_RENDER_RANGE) {
		if (diff == null) return;
		const { expandUnchanged = false, collapsedContextThreshold } = this.getOptionsWithDefaults();
		const cache = this.workerManager?.getDiffResultCache(diff);
		if (cache != null && this.renderCache == null) this.renderCache = {
			diff,
			highlighted: true,
			renderRange: void 0,
			...cache
		};
		const { options, forceRender } = this.getRenderOptions(diff);
		this.renderCache ??= {
			diff,
			highlighted: false,
			options,
			result: void 0,
			renderRange: void 0
		};
		if (this.workerManager?.isWorkingPool() === true) {
			if (this.renderCache.result == null || !this.renderCache.highlighted && !areRenderRangesEqual(this.renderCache.renderRange, renderRange)) {
				this.renderCache.result = this.workerManager.getPlainDiffAST(diff, renderRange.startingLine, renderRange.totalLines, isDefaultRenderRange(renderRange) ? true : expandUnchanged ? true : this.expandedHunks, collapsedContextThreshold);
				this.renderCache.renderRange = renderRange;
			}
			if (renderRange.totalLines > 0 && (!this.renderCache.highlighted || forceRender)) this.workerManager.highlightDiffAST(this, diff);
		} else {
			this.computedLang = diff.lang ?? getFiletypeFromFileName(diff.name);
			const hasThemes = this.highlighter != null && areThemesAttached(options.theme);
			const hasLangs = this.highlighter != null && areLanguagesAttached(this.computedLang);
			if (this.highlighter != null && hasThemes && (forceRender || !this.renderCache.highlighted && hasLangs || this.renderCache.result == null)) {
				const { result, options: options$1 } = this.renderDiffWithHighlighter(diff, this.highlighter, !hasLangs);
				this.renderCache = {
					diff,
					options: options$1,
					highlighted: hasLangs,
					result,
					renderRange: void 0
				};
			}
			if (!hasThemes || !hasLangs) this.asyncHighlight(diff).then(({ result, options: options$1 }) => {
				this.onHighlightSuccess(diff, result, options$1);
			});
		}
		return this.renderCache.result != null ? this.processDiffResult(this.renderCache.diff, renderRange, this.renderCache.result) : void 0;
	}
	async asyncRender(diff, renderRange = DEFAULT_RENDER_RANGE) {
		const { result } = await this.asyncHighlight(diff);
		return this.processDiffResult(diff, renderRange, result);
	}
	createPreElement(split, totalLines, themeStyles, baseThemeType) {
		const { diffIndicators, disableBackground, disableLineNumbers, overflow, themeType } = this.getOptionsWithDefaults();
		return createPreElement({
			type: "diff",
			diffIndicators,
			disableBackground,
			disableLineNumbers,
			overflow,
			themeStyles,
			split,
			themeType: baseThemeType ?? themeType,
			totalLines
		});
	}
	async asyncHighlight(diff) {
		this.computedLang = diff.lang ?? getFiletypeFromFileName(diff.name);
		const hasThemes = this.highlighter != null && areThemesAttached(this.options.theme ?? DEFAULT_THEMES);
		const hasLangs = this.highlighter != null && areLanguagesAttached(this.computedLang);
		if (this.highlighter == null || !hasThemes || !hasLangs) this.highlighter = await this.initializeHighlighter();
		return this.renderDiffWithHighlighter(diff, this.highlighter);
	}
	renderDiffWithHighlighter(diff, highlighter, forcePlainText = false) {
		const { options } = this.getRenderOptions(diff);
		const { collapsedContextThreshold } = this.getOptionsWithDefaults();
		return {
			result: renderDiffWithHighlighter(diff, highlighter, options, {
				forcePlainText,
				expandedHunks: forcePlainText ? true : void 0,
				collapsedContextThreshold
			}),
			options
		};
	}
	onHighlightSuccess(diff, result, options) {
		if (this.renderCache == null) return;
		const triggerRenderUpdate = this.renderCache.diff !== diff || !this.renderCache.highlighted || !areRenderOptionsEqual(this.renderCache.options, options);
		this.renderCache = {
			diff,
			options,
			highlighted: true,
			result,
			renderRange: void 0
		};
		if (triggerRenderUpdate) this.onRenderUpdate?.();
	}
	onHighlightError(error) {
		console.error(error);
	}
	processDiffResult(fileDiff, renderRange, { code, themeStyles, baseThemeType }) {
		const { diffStyle, disableFileHeader, expandUnchanged, expansionLineCount, collapsedContextThreshold, hunkSeparators } = this.getOptionsWithDefaults();
		this.diff = fileDiff;
		const unified = diffStyle === "unified";
		let additionsContentAST = [];
		let deletionsContentAST = [];
		let unifiedContentAST = [];
		const hunkData = [];
		const { additionLines, deletionLines } = code;
		const context = {
			rowCount: 0,
			hunkSeparators,
			additionsContentAST,
			deletionsContentAST,
			unifiedContentAST,
			unifiedGutterAST: createGutterWrapper(),
			deletionsGutterAST: createGutterWrapper(),
			additionsGutterAST: createGutterWrapper(),
			expansionLineCount,
			hunkData,
			incrementRowCount(count = 1) {
				context.rowCount += count;
			},
			pushToGutter(type, element) {
				switch (type) {
					case "unified":
						context.unifiedGutterAST.children.push(element);
						break;
					case "deletions":
						context.deletionsGutterAST.children.push(element);
						break;
					case "additions":
						context.additionsGutterAST.children.push(element);
						break;
				}
			}
		};
		const trailingRangeSize = calculateTrailingRangeSize(fileDiff);
		let pendingSplitSpanSize = 0;
		let pendingSplitMissing;
		function pushGutterLineNumber(type, lineType, lineNumber, lineIndex) {
			context.pushToGutter(type, createGutterItem(lineType, lineNumber, lineIndex));
		}
		function flushSplitSpan() {
			if (diffStyle === "unified") return;
			if (pendingSplitSpanSize <= 0 || pendingSplitMissing == null) {
				pendingSplitSpanSize = 0;
				pendingSplitMissing = void 0;
				return;
			}
			if (pendingSplitMissing === "additions") {
				context.pushToGutter("additions", createGutterGap(void 0, "buffer", pendingSplitSpanSize));
				additionsContentAST?.push(createEmptyRowBuffer(pendingSplitSpanSize));
			} else {
				context.pushToGutter("deletions", createGutterGap(void 0, "buffer", pendingSplitSpanSize));
				deletionsContentAST?.push(createEmptyRowBuffer(pendingSplitSpanSize));
			}
			pendingSplitSpanSize = 0;
			pendingSplitMissing = void 0;
		}
		function pushSeparators(props) {
			flushSplitSpan();
			if (diffStyle === "unified") pushSeparator("unified", props, context);
			else {
				pushSeparator("deletions", props, context);
				pushSeparator("additions", props, context);
			}
		}
		iterateOverDiff({
			diff: fileDiff,
			diffStyle,
			startingLine: renderRange.startingLine,
			totalLines: renderRange.totalLines,
			expandedHunks: expandUnchanged ? true : this.expandedHunks,
			collapsedContextThreshold,
			callback: ({ hunkIndex, hunk, collapsedBefore, collapsedAfter, additionLine, deletionLine, type }) => {
				const splitLineIndex = deletionLine != null ? deletionLine.splitLineIndex : additionLine.splitLineIndex;
				const unifiedLineIndex = additionLine != null ? additionLine.unifiedLineIndex : deletionLine.unifiedLineIndex;
				if (diffStyle === "split" && type !== "change") flushSplitSpan();
				if (collapsedBefore > 0) pushSeparators({
					hunkIndex,
					collapsedLines: collapsedBefore,
					rangeSize: Math.max(hunk?.collapsedBefore ?? 0, 0),
					hunkSpecs: hunk?.hunkSpecs,
					isFirstHunk: hunkIndex === 0,
					isLastHunk: false,
					isExpandable: !fileDiff.isPartial
				});
				const lineIndex = diffStyle === "unified" ? unifiedLineIndex : splitLineIndex;
				if (diffStyle === "unified") {
					const deletionLineContent = deletionLine != null ? deletionLines[deletionLine.lineIndex] : void 0;
					const additionLineContent = additionLine != null ? additionLines[additionLine.lineIndex] : void 0;
					if (deletionLineContent == null && additionLineContent == null) {
						const errorMessage = "DiffHunksRenderer.processDiffResult: deletionLine and additionLine are null, something is wrong";
						console.error(errorMessage, { file: fileDiff.name });
						throw new Error(errorMessage);
					}
					pushGutterLineNumber("unified", type === "change" ? additionLine != null ? "change-addition" : "change-deletion" : type, additionLine != null ? additionLine.lineNumber : deletionLine.lineNumber, `${unifiedLineIndex},${splitLineIndex}`);
					pushLineWithAnnotation({
						diffStyle: "unified",
						type,
						deletionLine: deletionLineContent,
						additionLine: additionLineContent,
						unifiedSpan: this.getAnnotations("unified", deletionLine?.lineNumber, additionLine?.lineNumber, hunkIndex, lineIndex),
						context
					});
				} else {
					const deletionLineContent = deletionLine != null ? deletionLines[deletionLine.lineIndex] : void 0;
					const additionLineContent = additionLine != null ? additionLines[additionLine.lineIndex] : void 0;
					if (deletionLineContent == null && additionLineContent == null) {
						const errorMessage = "DiffHunksRenderer.processDiffResult: deletionLine and additionLine are null, something is wrong";
						console.error(errorMessage, { file: fileDiff.name });
						throw new Error(errorMessage);
					}
					const missingSide = (() => {
						if (type === "change") {
							if (additionLineContent == null) return "additions";
							else if (deletionLineContent == null) return "deletions";
						}
					})();
					if (missingSide != null) {
						if (pendingSplitMissing != null && pendingSplitMissing !== missingSide) throw new Error("DiffHunksRenderer.processDiffResult: iterateOverDiff, invalid pending splits");
						pendingSplitMissing = missingSide;
						pendingSplitSpanSize++;
					}
					const annotationSpans = this.getAnnotations("split", deletionLine?.lineNumber, additionLine?.lineNumber, hunkIndex, lineIndex);
					if (annotationSpans != null && pendingSplitSpanSize > 0) flushSplitSpan();
					if (deletionLine != null) pushGutterLineNumber("deletions", type === "change" ? "change-deletion" : type, deletionLine.lineNumber, `${deletionLine.unifiedLineIndex},${splitLineIndex}`);
					if (additionLine != null) pushGutterLineNumber("additions", type === "change" ? "change-addition" : type, additionLine.lineNumber, `${additionLine.unifiedLineIndex},${splitLineIndex}`);
					pushLineWithAnnotation({
						diffStyle: "split",
						type,
						additionLine: additionLineContent,
						deletionLine: deletionLineContent,
						...annotationSpans,
						context
					});
				}
				const noEOFCRDeletion = deletionLine?.noEOFCR ?? false;
				const noEOFCRAddition = additionLine?.noEOFCR ?? false;
				if (noEOFCRAddition || noEOFCRDeletion) {
					if (noEOFCRDeletion) {
						const noEOFType = type === "context" || type === "context-expanded" ? type : "change-deletion";
						if (diffStyle === "unified") {
							context.unifiedContentAST.push(createNoNewlineElement(noEOFType));
							context.pushToGutter("unified", createGutterGap(noEOFType, "metadata", 1));
						} else {
							context.deletionsContentAST.push(createNoNewlineElement(noEOFType));
							context.pushToGutter("deletions", createGutterGap(noEOFType, "metadata", 1));
							if (!noEOFCRAddition) {
								context.pushToGutter("additions", createGutterGap(void 0, "buffer", 1));
								context.additionsContentAST.push(createEmptyRowBuffer(1));
							}
						}
					}
					if (noEOFCRAddition) {
						const noEOFType = type === "context" || type === "context-expanded" ? type : "change-addition";
						if (diffStyle === "unified") {
							context.unifiedContentAST.push(createNoNewlineElement(noEOFType));
							context.pushToGutter("unified", createGutterGap(noEOFType, "metadata", 1));
						} else {
							context.additionsContentAST.push(createNoNewlineElement(noEOFType));
							context.pushToGutter("additions", createGutterGap(noEOFType, "metadata", 1));
							if (!noEOFCRDeletion) {
								context.pushToGutter("deletions", createGutterGap(void 0, "buffer", 1));
								context.deletionsContentAST.push(createEmptyRowBuffer(1));
							}
						}
					}
					context.incrementRowCount(1);
				}
				if (collapsedAfter > 0 && hunkSeparators !== "simple") pushSeparators({
					hunkIndex: type === "context-expanded" ? hunkIndex : hunkIndex + 1,
					collapsedLines: collapsedAfter,
					rangeSize: trailingRangeSize,
					hunkSpecs: void 0,
					isFirstHunk: false,
					isLastHunk: true,
					isExpandable: !fileDiff.isPartial
				});
				context.incrementRowCount(1);
			}
		});
		if (diffStyle === "split") flushSplitSpan();
		const totalLines = Math.max(getTotalLineCountFromHunks(fileDiff.hunks), fileDiff.additionLines.length ?? 0, fileDiff.deletionLines.length ?? 0);
		const hasBuffer = renderRange.bufferBefore > 0 || renderRange.bufferAfter > 0;
		const shouldIncludeAdditions = !unified && fileDiff.type !== "deleted";
		const shouldIncludeDeletions = !unified && fileDiff.type !== "new";
		const hasContent = context.rowCount > 0 || hasBuffer;
		additionsContentAST = shouldIncludeAdditions && hasContent ? additionsContentAST : void 0;
		deletionsContentAST = shouldIncludeDeletions && hasContent ? deletionsContentAST : void 0;
		unifiedContentAST = unified && hasContent ? unifiedContentAST : void 0;
		const preNode = this.createPreElement(deletionsContentAST != null && additionsContentAST != null, totalLines, themeStyles, baseThemeType);
		return {
			unifiedGutterAST: unified && hasContent ? context.unifiedGutterAST.children : void 0,
			unifiedContentAST,
			deletionsGutterAST: shouldIncludeDeletions && hasContent ? context.deletionsGutterAST.children : void 0,
			deletionsContentAST,
			additionsGutterAST: shouldIncludeAdditions && hasContent ? context.additionsGutterAST.children : void 0,
			additionsContentAST,
			hunkData,
			preNode,
			themeStyles,
			baseThemeType,
			headerElement: !disableFileHeader ? this.renderHeader(this.diff, themeStyles, baseThemeType) : void 0,
			totalLines,
			rowCount: context.rowCount,
			bufferBefore: renderRange.bufferBefore,
			bufferAfter: renderRange.bufferAfter,
			css: ""
		};
	}
	renderCodeAST(type, result) {
		const gutterAST = type === "unified" ? result.unifiedGutterAST : type === "deletions" ? result.deletionsGutterAST : result.additionsGutterAST;
		const contentAST = type === "unified" ? result.unifiedContentAST : type === "deletions" ? result.deletionsContentAST : result.additionsContentAST;
		if (gutterAST == null || contentAST == null) return;
		const gutter = createGutterWrapper(gutterAST);
		gutter.properties.style = `grid-row: span ${result.rowCount}`;
		return [gutter, createContentColumn(contentAST, result.rowCount)];
	}
	renderFullAST(result, children = []) {
		const unifiedAST = this.renderCodeAST("unified", result);
		if (unifiedAST != null) {
			children.push(createHastElement({
				tagName: "code",
				children: unifiedAST,
				properties: {
					"data-code": "",
					"data-unified": ""
				}
			}));
			return {
				...result.preNode,
				children
			};
		}
		const deletionsAST = this.renderCodeAST("deletions", result);
		if (deletionsAST != null) children.push(createHastElement({
			tagName: "code",
			children: deletionsAST,
			properties: {
				"data-code": "",
				"data-deletions": ""
			}
		}));
		const additionsAST = this.renderCodeAST("additions", result);
		if (additionsAST != null) children.push(createHastElement({
			tagName: "code",
			children: additionsAST,
			properties: {
				"data-code": "",
				"data-additions": ""
			}
		}));
		return {
			...result.preNode,
			children
		};
	}
	renderFullHTML(result, tempChildren = []) {
		return toHtml(this.renderFullAST(result, tempChildren));
	}
	renderPartialHTML(children, columnType) {
		if (columnType == null) return toHtml(children);
		return toHtml(createHastElement({
			tagName: "code",
			children,
			properties: {
				"data-code": "",
				[`data-${columnType}`]: ""
			}
		}));
	}
	getAnnotations(type, deletionLineNumber, additionLineNumber, hunkIndex, lineIndex) {
		const deletionSpan = {
			type: "annotation",
			hunkIndex,
			lineIndex,
			annotations: []
		};
		if (deletionLineNumber != null) for (const anno of this.deletionAnnotations[deletionLineNumber] ?? []) deletionSpan.annotations.push(getLineAnnotationName(anno));
		const additionSpan = {
			type: "annotation",
			hunkIndex,
			lineIndex,
			annotations: []
		};
		if (additionLineNumber != null) for (const anno of this.additionAnnotations[additionLineNumber] ?? []) (type === "unified" ? deletionSpan : additionSpan).annotations.push(getLineAnnotationName(anno));
		if (type === "unified") {
			if (deletionSpan.annotations.length > 0) return deletionSpan;
			return;
		}
		if (additionSpan.annotations.length === 0 && deletionSpan.annotations.length === 0) return;
		return {
			deletionSpan,
			additionSpan
		};
	}
	renderHeader(diff, themeStyles, baseThemeType) {
		const { themeType } = this.getOptionsWithDefaults();
		return createFileHeaderElement({
			fileOrDiff: diff,
			themeStyles,
			themeType: baseThemeType ?? themeType
		});
	}
};
function areRenderOptionsEqual(optionsA, optionsB) {
	return areThemesEqual(optionsA.theme, optionsB.theme) && optionsA.tokenizeMaxLineLength === optionsB.tokenizeMaxLineLength && optionsA.lineDiffType === optionsB.lineDiffType;
}
function getModifiedLinesString(lines) {
	return `${lines} unmodified line${lines > 1 ? "s" : ""}`;
}
function pushLineWithAnnotation({ diffStyle, type, deletionLine, additionLine, unifiedSpan, deletionSpan, additionSpan, context }) {
	let hasAnnotationRow = false;
	if (diffStyle === "unified") {
		if (additionLine != null) context.unifiedContentAST.push(additionLine);
		else if (deletionLine != null) context.unifiedContentAST.push(deletionLine);
		if (unifiedSpan != null) {
			const lineType = type === "change" ? deletionLine != null ? "change-deletion" : "change-addition" : type;
			context.unifiedContentAST.push(createAnnotationElement(unifiedSpan));
			context.pushToGutter("unified", createGutterGap(lineType, "annotation", 1));
			hasAnnotationRow = true;
		}
	} else if (diffStyle === "split") {
		if (deletionLine != null) context.deletionsContentAST.push(deletionLine);
		if (additionLine != null) context.additionsContentAST.push(additionLine);
		if (deletionSpan != null) {
			const lineType = type === "change" ? deletionLine != null ? "change-deletion" : "context" : type;
			context.deletionsContentAST.push(createAnnotationElement(deletionSpan));
			context.pushToGutter("deletions", createGutterGap(lineType, "annotation", 1));
			hasAnnotationRow = true;
		}
		if (additionSpan != null) {
			const lineType = type === "change" ? additionLine != null ? "change-addition" : "context" : type;
			context.additionsContentAST.push(createAnnotationElement(additionSpan));
			context.pushToGutter("additions", createGutterGap(lineType, "annotation", 1));
			hasAnnotationRow = true;
		}
	}
	if (hasAnnotationRow) context.incrementRowCount(1);
}
function pushSeparator(type, { hunkIndex, collapsedLines, rangeSize, hunkSpecs, isFirstHunk, isLastHunk, isExpandable }, context) {
	if (collapsedLines <= 0) return;
	const linesAST = type === "unified" ? context.unifiedContentAST : type === "deletions" ? context.deletionsContentAST : context.additionsContentAST;
	if (context.hunkSeparators === "metadata") {
		if (hunkSpecs != null) {
			context.pushToGutter(type, createSeparator({
				type: "metadata",
				content: hunkSpecs,
				isFirstHunk,
				isLastHunk
			}));
			linesAST.push(createSeparator({
				type: "metadata",
				content: hunkSpecs,
				isFirstHunk,
				isLastHunk
			}));
			if (type !== "additions") context.incrementRowCount(1);
		}
		return;
	}
	if (context.hunkSeparators === "simple") {
		if (hunkIndex > 0) {
			context.pushToGutter(type, createSeparator({
				type: "simple",
				isFirstHunk,
				isLastHunk: false
			}));
			linesAST.push(createSeparator({
				type: "simple",
				isFirstHunk,
				isLastHunk: false
			}));
			if (type !== "additions") context.incrementRowCount(1);
		}
		return;
	}
	const slotName = getHunkSeparatorSlotName(type, hunkIndex);
	const chunked = rangeSize > context.expansionLineCount;
	const expandIndex = isExpandable ? hunkIndex : void 0;
	context.pushToGutter(type, createSeparator({
		type: context.hunkSeparators,
		content: getModifiedLinesString(collapsedLines),
		expandIndex,
		chunked,
		slotName,
		isFirstHunk,
		isLastHunk
	}));
	linesAST.push(createSeparator({
		type: context.hunkSeparators,
		content: getModifiedLinesString(collapsedLines),
		expandIndex,
		chunked,
		slotName,
		isFirstHunk,
		isLastHunk
	}));
	if (type !== "additions") context.incrementRowCount(1);
	context.hunkData.push({
		slotName,
		hunkIndex,
		lines: collapsedLines,
		type,
		expandable: isExpandable ? {
			up: !isFirstHunk,
			down: !isLastHunk,
			chunked
		} : void 0
	});
}
function calculateTrailingRangeSize(fileDiff) {
	const lastHunk = fileDiff.hunks.at(-1);
	if (lastHunk == null || fileDiff.isPartial || fileDiff.additionLines.length === 0 || fileDiff.deletionLines.length === 0) return 0;
	const additionRemaining = fileDiff.additionLines.length - (lastHunk.additionLineIndex + lastHunk.additionCount);
	const deletionRemaining = fileDiff.deletionLines.length - (lastHunk.deletionLineIndex + lastHunk.deletionCount);
	if (additionRemaining !== deletionRemaining) throw new Error(`DiffHunksRenderer.processDiffResult: trailing context mismatch (additions=${additionRemaining}, deletions=${deletionRemaining}) for ${fileDiff.name}`);
	return Math.min(additionRemaining, deletionRemaining);
}

//#endregion
export { DiffHunksRenderer };
//# sourceMappingURL=DiffHunksRenderer.js.map