import { __decorate, __param } from '../../../../../../../../external/tslib/tslib.es6.js';
import { isAncestorOfActiveElement, getActiveWindow, addDisposableListener, getWindow, getDocument, EventType } from '../../../../../base/browser/dom.js';
import { IConfigurationService } from '../../../../../platform/configuration/common/configuration.js';
import { Disposable, DisposableStore } from '../../../../../base/common/lifecycle.js';
import { ITerminalLogService } from '../../../../../platform/terminal/common/terminal.js';
import { isSafari } from '../../../../../base/browser/browser.js';
import { LogLevel } from '../../../../../platform/log/common/log.js';
import { IStorageService } from '../../../../../platform/storage/common/storage.js';
import { Severity, INotificationService } from '../../../../../platform/notification/common/notification.js';
import { MarkNavigationAddon } from './markNavigationAddon.js';
import { localizeWithPath } from '../../../../../nls.js';
import { IThemeService } from '../../../../../platform/theme/common/themeService.js';
import { PANEL_BACKGROUND } from '../../../../common/theme.js';
import { TERMINAL_BACKGROUND_COLOR, TERMINAL_FIND_MATCH_BACKGROUND_COLOR, TERMINAL_FIND_MATCH_BORDER_COLOR, TERMINAL_OVERVIEW_RULER_CURSOR_FOREGROUND_COLOR, TERMINAL_FIND_MATCH_HIGHLIGHT_BACKGROUND_COLOR, TERMINAL_FIND_MATCH_HIGHLIGHT_BORDER_COLOR, TERMINAL_OVERVIEW_RULER_FIND_MATCH_FOREGROUND_COLOR, TERMINAL_FOREGROUND_COLOR, TERMINAL_CURSOR_FOREGROUND_COLOR, TERMINAL_CURSOR_BACKGROUND_COLOR, TERMINAL_SELECTION_BACKGROUND_COLOR, TERMINAL_INACTIVE_SELECTION_BACKGROUND_COLOR, TERMINAL_SELECTION_FOREGROUND_COLOR, ansiColorIdentifiers } from '../../common/terminalColorRegistry.js';
import { ShellIntegrationAddon } from '../../../../../platform/terminal/common/xterm/shellIntegrationAddon.js';
import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js';
import { DecorationAddon } from './decorationAddon.js';
import { Emitter } from '../../../../../base/common/event.js';
import { ITelemetryService } from '../../../../../platform/telemetry/common/telemetry.js';
import { IContextKeyService } from '../../../../../platform/contextkey/common/contextkey.js';
import { TerminalContextKeys } from '../../common/terminalContextKey.js';
import { IClipboardService } from '../../../../../platform/clipboard/common/clipboardService.js';
import { debounce } from '../../../../../base/common/decorators.js';
import { MouseWheelClassifier } from '../../../../../base/browser/ui/scrollbar/scrollableElement.js';
import { StandardWheelEvent } from '../../../../../base/browser/mouseEvent.js';
import { ILayoutService } from '../../../../../platform/layout/browser/layoutService.js';
import { AccessibilitySignal, IAccessibilitySignalService } from '../../../../../platform/accessibilitySignal/browser/accessibilitySignalService.js';
var XtermTerminal_1;
let CanvasAddon;
let ImageAddon;
let SearchAddon;
let SerializeAddon;
let Unicode11Addon;
let WebglAddon;
function getFullBufferLineAsString(lineIndex, buffer) {
    let line = buffer.getLine(lineIndex);
    if (!line) {
        return { lineData: undefined, lineIndex };
    }
    let lineData = line.translateToString(true);
    while (lineIndex > 0 && line.isWrapped) {
        line = buffer.getLine(--lineIndex);
        if (!line) {
            break;
        }
        lineData = line.translateToString(false) + lineData;
    }
    return { lineData, lineIndex };
}
let XtermTerminal = class XtermTerminal extends Disposable {
    static { XtermTerminal_1 = this; }
    static { this._suggestedRendererType = undefined; }
    static { this._checkedWebglCompatible = false; }
    get findResult() { return this._lastFindResult; }
    get isStdinDisabled() { return !!this.raw.options.disableStdin; }
    get isGpuAccelerated() { return !!(this._canvasAddon || this._webglAddon); }
    get markTracker() { return this._markNavigationAddon; }
    get shellIntegration() { return this._shellIntegrationAddon; }
    get textureAtlas() {
        const canvas = this._webglAddon?.textureAtlas || this._canvasAddon?.textureAtlas;
        if (!canvas) {
            return undefined;
        }
        return createImageBitmap(canvas);
    }
    get isFocused() {
        if (!this.raw.element) {
            return false;
        }
        return isAncestorOfActiveElement(this.raw.element);
    }
    constructor(xtermCtor, _configHelper, cols, rows, _xtermColorProvider, _capabilities, shellIntegrationNonce, disableShellIntegrationReporting, _configurationService, _instantiationService, _logService, _notificationService, _storageService, _themeService, _telemetryService, _clipboardService, contextKeyService, _accessibilitySignalService, layoutService) {
        super();
        this._configHelper = _configHelper;
        this._xtermColorProvider = _xtermColorProvider;
        this._capabilities = _capabilities;
        this._configurationService = _configurationService;
        this._instantiationService = _instantiationService;
        this._logService = _logService;
        this._notificationService = _notificationService;
        this._storageService = _storageService;
        this._themeService = _themeService;
        this._telemetryService = _telemetryService;
        this._clipboardService = _clipboardService;
        this._accessibilitySignalService = _accessibilitySignalService;
        this._isPhysicalMouseWheel = MouseWheelClassifier.INSTANCE.isPhysicalMouseWheel();
        this._attachedDisposables = this._register(( new DisposableStore()));
        this._onDidRequestRunCommand = this._register(( new Emitter()));
        this.onDidRequestRunCommand = this._onDidRequestRunCommand.event;
        this._onDidRequestFocus = this._register(( new Emitter()));
        this.onDidRequestFocus = this._onDidRequestFocus.event;
        this._onDidRequestSendText = this._register(( new Emitter()));
        this.onDidRequestSendText = this._onDidRequestSendText.event;
        this._onDidRequestFreePort = this._register(( new Emitter()));
        this.onDidRequestFreePort = this._onDidRequestFreePort.event;
        this._onDidChangeFindResults = this._register(( new Emitter()));
        this.onDidChangeFindResults = this._onDidChangeFindResults.event;
        this._onDidChangeSelection = this._register(( new Emitter()));
        this.onDidChangeSelection = this._onDidChangeSelection.event;
        this._onDidChangeFocus = this._register(( new Emitter()));
        this.onDidChangeFocus = this._onDidChangeFocus.event;
        this._onDidDispose = this._register(( new Emitter()));
        this.onDidDispose = this._onDidDispose.event;
        const font = this._configHelper.getFont(getActiveWindow(), undefined, true);
        const config = this._configHelper.config;
        const editorOptions = this._configurationService.getValue('editor');
        this.raw = this._register(( new xtermCtor({
            allowProposedApi: true,
            cols,
            rows,
            documentOverride: layoutService.mainContainer.ownerDocument,
            altClickMovesCursor: config.altClickMovesCursor && editorOptions.multiCursorModifier === 'alt',
            scrollback: config.scrollback,
            theme: this.getXtermTheme(),
            drawBoldTextInBrightColors: config.drawBoldTextInBrightColors,
            fontFamily: font.fontFamily,
            fontWeight: config.fontWeight,
            fontWeightBold: config.fontWeightBold,
            fontSize: font.fontSize,
            letterSpacing: font.letterSpacing,
            lineHeight: font.lineHeight,
            logLevel: vscodeToXtermLogLevel(this._logService.getLevel()),
            logger: this._logService,
            minimumContrastRatio: config.minimumContrastRatio,
            tabStopWidth: config.tabStopWidth,
            cursorBlink: config.cursorBlinking,
            cursorStyle: vscodeToXtermCursorStyle(config.cursorStyle),
            cursorInactiveStyle: vscodeToXtermCursorStyle(config.cursorStyleInactive),
            cursorWidth: config.cursorWidth,
            macOptionIsMeta: config.macOptionIsMeta,
            macOptionClickForcesSelection: config.macOptionClickForcesSelection,
            rightClickSelectsWord: config.rightClickBehavior === 'selectWord',
            fastScrollModifier: 'alt',
            fastScrollSensitivity: config.fastScrollSensitivity,
            scrollSensitivity: config.mouseWheelScrollSensitivity,
            wordSeparator: config.wordSeparators,
            overviewRulerWidth: 10,
            ignoreBracketedPasteMode: config.ignoreBracketedPasteMode,
            rescaleOverlappingGlyphs: config.rescaleOverlappingGlyphs,
        })));
        this._updateSmoothScrolling();
        this._core = this.raw._core;
        this._register(this._configurationService.onDidChangeConfiguration(async (e) => {
            if (e.affectsConfiguration("terminal.integrated.gpuAcceleration" )) {
                XtermTerminal_1._suggestedRendererType = undefined;
            }
            if (e.affectsConfiguration('terminal.integrated') || e.affectsConfiguration('editor.fastScrollSensitivity') || e.affectsConfiguration('editor.mouseWheelScrollSensitivity') || e.affectsConfiguration('editor.multiCursorModifier')) {
                this.updateConfig();
            }
            if (e.affectsConfiguration("terminal.integrated.unicodeVersion" )) {
                this._updateUnicodeVersion();
            }
        }));
        this._register(this._themeService.onDidColorThemeChange(theme => this._updateTheme(theme)));
        this._register(this._logService.onDidChangeLogLevel(e => this.raw.options.logLevel = vscodeToXtermLogLevel(e)));
        this._register(this.raw.onSelectionChange(() => {
            this._onDidChangeSelection.fire();
            if (this.isFocused) {
                this._anyFocusedTerminalHasSelection.set(this.raw.hasSelection());
            }
        }));
        this._updateUnicodeVersion();
        this._markNavigationAddon = this._instantiationService.createInstance(MarkNavigationAddon, _capabilities);
        this.raw.loadAddon(this._markNavigationAddon);
        this._decorationAddon = this._instantiationService.createInstance(DecorationAddon, this._capabilities);
        this._register(this._decorationAddon.onDidRequestRunCommand(e => this._onDidRequestRunCommand.fire(e)));
        this.raw.loadAddon(this._decorationAddon);
        this._shellIntegrationAddon = ( new ShellIntegrationAddon(
            shellIntegrationNonce,
            disableShellIntegrationReporting,
            this._telemetryService,
            this._logService
        ));
        this.raw.loadAddon(this._shellIntegrationAddon);
        this._anyTerminalFocusContextKey = TerminalContextKeys.focusInAny.bindTo(contextKeyService);
        this._anyFocusedTerminalHasSelection = TerminalContextKeys.textSelectedInFocused.bindTo(contextKeyService);
    }
    *getBufferReverseIterator() {
        for (let i = this.raw.buffer.active.length; i >= 0; i--) {
            const { lineData, lineIndex } = getFullBufferLineAsString(i, this.raw.buffer.active);
            if (lineData) {
                i = lineIndex;
                yield lineData;
            }
        }
    }
    async getContentsAsHtml() {
        if (!this._serializeAddon) {
            const Addon = await this._getSerializeAddonConstructor();
            this._serializeAddon = ( new Addon());
            this.raw.loadAddon(this._serializeAddon);
        }
        return this._serializeAddon.serializeAsHTML();
    }
    async getSelectionAsHtml(command) {
        if (!this._serializeAddon) {
            const Addon = await this._getSerializeAddonConstructor();
            this._serializeAddon = ( new Addon());
            this.raw.loadAddon(this._serializeAddon);
        }
        if (command) {
            const length = command.getOutput()?.length;
            const row = command.marker?.line;
            if (!length || !row) {
                throw new Error(`No row ${row} or output length ${length} for command ${command}`);
            }
            this.raw.select(0, row + 1, length - Math.floor(length / this.raw.cols));
        }
        const result = this._serializeAddon.serializeAsHTML({ onlySelection: true });
        if (command) {
            this.raw.clearSelection();
        }
        return result;
    }
    attachToElement(container, partialOptions) {
        const options = { enableGpu: true, ...partialOptions };
        if (!this._attached) {
            this.raw.open(container);
        }
        if (options.enableGpu) {
            if (this._shouldLoadWebgl()) {
                this._enableWebglRenderer();
            }
            else if (this._shouldLoadCanvas()) {
                this._enableCanvasRenderer();
            }
        }
        if (!this.raw.element || !this.raw.textarea) {
            throw new Error('xterm elements not set after open');
        }
        const ad = this._attachedDisposables;
        ad.clear();
        ad.add(addDisposableListener(this.raw.textarea, 'focus', () => this._setFocused(true)));
        ad.add(addDisposableListener(this.raw.textarea, 'blur', () => this._setFocused(false)));
        ad.add(addDisposableListener(this.raw.textarea, 'focusout', () => this._setFocused(false)));
        ad.add(addDisposableListener(this.raw.element, EventType.MOUSE_WHEEL, (e) => {
            const classifier = MouseWheelClassifier.INSTANCE;
            classifier.acceptStandardWheelEvent(( new StandardWheelEvent(e)));
            const value = classifier.isPhysicalMouseWheel();
            if (value !== this._isPhysicalMouseWheel) {
                this._isPhysicalMouseWheel = value;
                this._updateSmoothScrolling();
            }
        }, { passive: true }));
        this._attached = { container, options };
        return this._attached?.container.querySelector('.xterm-screen');
    }
    _setFocused(isFocused) {
        this._onDidChangeFocus.fire(isFocused);
        this._anyTerminalFocusContextKey.set(isFocused);
        this._anyFocusedTerminalHasSelection.set(isFocused && this.raw.hasSelection());
    }
    write(data, callback) {
        this.raw.write(data, callback);
    }
    resize(columns, rows) {
        this.raw.resize(columns, rows);
    }
    updateConfig() {
        const config = this._configHelper.config;
        this.raw.options.altClickMovesCursor = config.altClickMovesCursor;
        this._setCursorBlink(config.cursorBlinking);
        this._setCursorStyle(config.cursorStyle);
        this._setCursorStyleInactive(config.cursorStyleInactive);
        this._setCursorWidth(config.cursorWidth);
        this.raw.options.scrollback = config.scrollback;
        this.raw.options.drawBoldTextInBrightColors = config.drawBoldTextInBrightColors;
        this.raw.options.minimumContrastRatio = config.minimumContrastRatio;
        this.raw.options.tabStopWidth = config.tabStopWidth;
        this.raw.options.fastScrollSensitivity = config.fastScrollSensitivity;
        this.raw.options.scrollSensitivity = config.mouseWheelScrollSensitivity;
        this.raw.options.macOptionIsMeta = config.macOptionIsMeta;
        const editorOptions = this._configurationService.getValue('editor');
        this.raw.options.altClickMovesCursor = config.altClickMovesCursor && editorOptions.multiCursorModifier === 'alt';
        this.raw.options.macOptionClickForcesSelection = config.macOptionClickForcesSelection;
        this.raw.options.rightClickSelectsWord = config.rightClickBehavior === 'selectWord';
        this.raw.options.wordSeparator = config.wordSeparators;
        this.raw.options.customGlyphs = config.customGlyphs;
        this.raw.options.ignoreBracketedPasteMode = config.ignoreBracketedPasteMode;
        this.raw.options.rescaleOverlappingGlyphs = config.rescaleOverlappingGlyphs;
        this._updateSmoothScrolling();
        if (this._attached?.options.enableGpu) {
            if (this._shouldLoadWebgl()) {
                this._enableWebglRenderer();
            }
            else {
                this._disposeOfWebglRenderer();
                if (this._shouldLoadCanvas()) {
                    this._enableCanvasRenderer();
                }
                else {
                    this._disposeOfCanvasRenderer();
                }
            }
        }
    }
    _updateSmoothScrolling() {
        this.raw.options.smoothScrollDuration = this._configHelper.config.smoothScrolling && this._isPhysicalMouseWheel ? 125  : 0;
    }
    _shouldLoadWebgl() {
        return !isSafari && (this._configHelper.config.gpuAcceleration === 'auto' && XtermTerminal_1._suggestedRendererType === undefined) || this._configHelper.config.gpuAcceleration === 'on';
    }
    _shouldLoadCanvas() {
        return (this._configHelper.config.gpuAcceleration === 'auto' && (XtermTerminal_1._suggestedRendererType === undefined || XtermTerminal_1._suggestedRendererType === 'canvas')) || this._configHelper.config.gpuAcceleration === 'canvas';
    }
    forceRedraw() {
        this.raw.clearTextureAtlas();
    }
    clearDecorations() {
        this._decorationAddon?.clearDecorations();
    }
    forceRefresh() {
        this._core.viewport?._innerRefresh();
    }
    forceUnpause() {
        if (!!this._canvasAddon) {
            this._core._renderService?._handleIntersectionChange({ intersectionRatio: 1 });
            this.raw.refresh(0, this.raw.rows - 1);
        }
    }
    async findNext(term, searchOptions) {
        this._updateFindColors(searchOptions);
        return (await this._getSearchAddon()).findNext(term, searchOptions);
    }
    async findPrevious(term, searchOptions) {
        this._updateFindColors(searchOptions);
        return (await this._getSearchAddon()).findPrevious(term, searchOptions);
    }
    _updateFindColors(searchOptions) {
        const theme = this._themeService.getColorTheme();
        const terminalBackground = theme.getColor(TERMINAL_BACKGROUND_COLOR) || theme.getColor(PANEL_BACKGROUND);
        const findMatchBackground = theme.getColor(TERMINAL_FIND_MATCH_BACKGROUND_COLOR);
        const findMatchBorder = theme.getColor(TERMINAL_FIND_MATCH_BORDER_COLOR);
        const findMatchOverviewRuler = theme.getColor(TERMINAL_OVERVIEW_RULER_CURSOR_FOREGROUND_COLOR);
        const findMatchHighlightBackground = theme.getColor(TERMINAL_FIND_MATCH_HIGHLIGHT_BACKGROUND_COLOR);
        const findMatchHighlightBorder = theme.getColor(TERMINAL_FIND_MATCH_HIGHLIGHT_BORDER_COLOR);
        const findMatchHighlightOverviewRuler = theme.getColor(TERMINAL_OVERVIEW_RULER_FIND_MATCH_FOREGROUND_COLOR);
        searchOptions.decorations = {
            activeMatchBackground: findMatchBackground?.toString(),
            activeMatchBorder: findMatchBorder?.toString() || 'transparent',
            activeMatchColorOverviewRuler: findMatchOverviewRuler?.toString() || 'transparent',
            matchBackground: terminalBackground ? findMatchHighlightBackground?.blend(terminalBackground).toString() : undefined,
            matchBorder: findMatchHighlightBorder?.toString() || 'transparent',
            matchOverviewRuler: findMatchHighlightOverviewRuler?.toString() || 'transparent'
        };
    }
    _getSearchAddon() {
        if (!this._searchAddonPromise) {
            this._searchAddonPromise = this._getSearchAddonConstructor().then((AddonCtor) => {
                this._searchAddon = ( new AddonCtor({ highlightLimit: 1000  }));
                this.raw.loadAddon(this._searchAddon);
                this._searchAddon.onDidChangeResults((results) => {
                    this._lastFindResult = results;
                    this._onDidChangeFindResults.fire(results);
                });
                return this._searchAddon;
            });
        }
        return this._searchAddonPromise;
    }
    clearSearchDecorations() {
        this._searchAddon?.clearDecorations();
    }
    clearActiveSearchDecoration() {
        this._searchAddon?.clearActiveDecoration();
    }
    getFont() {
        return this._configHelper.getFont(getWindow(this.raw.element), this._core);
    }
    getLongestViewportWrappedLineLength() {
        let maxLineLength = 0;
        for (let i = this.raw.buffer.active.length - 1; i >= this.raw.buffer.active.viewportY; i--) {
            const lineInfo = this._getWrappedLineCount(i, this.raw.buffer.active);
            maxLineLength = Math.max(maxLineLength, ((lineInfo.lineCount * this.raw.cols) - lineInfo.endSpaces) || 0);
            i = lineInfo.currentIndex;
        }
        return maxLineLength;
    }
    _getWrappedLineCount(index, buffer) {
        let line = buffer.getLine(index);
        if (!line) {
            throw new Error('Could not get line');
        }
        let currentIndex = index;
        let endSpaces = 0;
        for (let i = Math.min(line.length, this.raw.cols) - 1; i >= 0; i--) {
            if (!line?.getCell(i)?.getChars()) {
                endSpaces++;
            }
            else {
                break;
            }
        }
        while (line?.isWrapped && currentIndex > 0) {
            currentIndex--;
            line = buffer.getLine(currentIndex);
        }
        return { lineCount: index - currentIndex + 1, currentIndex, endSpaces };
    }
    scrollDownLine() {
        this.raw.scrollLines(1);
    }
    scrollDownPage() {
        this.raw.scrollPages(1);
    }
    scrollToBottom() {
        this.raw.scrollToBottom();
    }
    scrollUpLine() {
        this.raw.scrollLines(-1);
    }
    scrollUpPage() {
        this.raw.scrollPages(-1);
    }
    scrollToTop() {
        this.raw.scrollToTop();
    }
    scrollToLine(line, position = 0 ) {
        this.markTracker.scrollToLine(line, position);
    }
    clearBuffer() {
        this.raw.clear();
        this._capabilities.get(2 )?.handlePromptStart();
        this._capabilities.get(2 )?.handleCommandStart();
        this._accessibilitySignalService.playSignal(AccessibilitySignal.clear);
    }
    hasSelection() {
        return this.raw.hasSelection();
    }
    clearSelection() {
        this.raw.clearSelection();
    }
    selectMarkedRange(fromMarkerId, toMarkerId, scrollIntoView = false) {
        const detectionCapability = this.shellIntegration.capabilities.get(4 );
        if (!detectionCapability) {
            return;
        }
        const start = detectionCapability.getMark(fromMarkerId);
        const end = detectionCapability.getMark(toMarkerId);
        if (start === undefined || end === undefined) {
            return;
        }
        this.raw.selectLines(start.line, end.line);
        if (scrollIntoView) {
            this.raw.scrollToLine(start.line);
        }
    }
    selectAll() {
        this.raw.focus();
        this.raw.selectAll();
    }
    focus() {
        this.raw.focus();
    }
    async copySelection(asHtml, command) {
        if (this.hasSelection() || (asHtml && command)) {
            if (asHtml) {
                const textAsHtml = await this.getSelectionAsHtml(command);
                function listener(e) {
                    if (!e.clipboardData.types.includes('text/plain')) {
                        e.clipboardData.setData('text/plain', command?.getOutput() ?? '');
                    }
                    e.clipboardData.setData('text/html', textAsHtml);
                    e.preventDefault();
                }
                const doc = getDocument(this.raw.element);
                doc.addEventListener('copy', listener);
                doc.execCommand('copy');
                doc.removeEventListener('copy', listener);
            }
            else {
                await this._clipboardService.writeText(this.raw.getSelection());
            }
        }
        else {
            this._notificationService.warn(( localizeWithPath(
                'vs/workbench/contrib/terminal/browser/xterm/xtermTerminal',
                'terminal.integrated.copySelection.noSelection',
                'The terminal has no selection to copy'
            )));
        }
    }
    _setCursorBlink(blink) {
        if (this.raw.options.cursorBlink !== blink) {
            this.raw.options.cursorBlink = blink;
            this.raw.refresh(0, this.raw.rows - 1);
        }
    }
    _setCursorStyle(style) {
        const mapped = vscodeToXtermCursorStyle(style);
        if (this.raw.options.cursorStyle !== mapped) {
            this.raw.options.cursorStyle = mapped;
        }
    }
    _setCursorStyleInactive(style) {
        const mapped = vscodeToXtermCursorStyle(style);
        if (this.raw.options.cursorInactiveStyle !== mapped) {
            this.raw.options.cursorInactiveStyle = mapped;
        }
    }
    _setCursorWidth(width) {
        if (this.raw.options.cursorWidth !== width) {
            this.raw.options.cursorWidth = width;
        }
    }
    async _enableWebglRenderer() {
        if (!this.raw.element || this._webglAddon) {
            return;
        }
        if (!XtermTerminal_1._checkedWebglCompatible) {
            XtermTerminal_1._checkedWebglCompatible = true;
            const checkCanvas = document.createElement('canvas');
            const checkGl = checkCanvas.getContext('webgl2');
            const debugInfo = checkGl?.getExtension('WEBGL_debug_renderer_info');
            if (checkGl && debugInfo) {
                const renderer = checkGl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);
                if (renderer.startsWith('ANGLE (Google, Vulkan 1.3.0 (SwiftShader Device (Subzero)')) {
                    this._disableWebglForThisSession();
                    return;
                }
            }
        }
        const Addon = await this._getWebglAddonConstructor();
        this._webglAddon = ( new Addon());
        this._disposeOfCanvasRenderer();
        try {
            this.raw.loadAddon(this._webglAddon);
            this._logService.trace('Webgl was loaded');
            this._webglAddon.onContextLoss(() => {
                this._logService.info(`Webgl lost context, disposing of webgl renderer`);
                this._disposeOfWebglRenderer();
            });
            this._refreshImageAddon();
        }
        catch (e) {
            this._logService.warn(`Webgl could not be loaded. Falling back to the canvas renderer type.`, e);
            const neverMeasureRenderTime = this._storageService.getBoolean("terminal.integrated.neverMeasureRenderTime" , -1 , false);
            if (!neverMeasureRenderTime && this._configHelper.config.gpuAcceleration !== 'off') {
                this._measureRenderTime();
            }
            this._disableWebglForThisSession();
        }
    }
    _disableWebglForThisSession() {
        XtermTerminal_1._suggestedRendererType = 'canvas';
        this._disposeOfWebglRenderer();
        this._enableCanvasRenderer();
    }
    async _enableCanvasRenderer() {
        if (!this.raw.element || this._canvasAddon) {
            return;
        }
        const Addon = await this._getCanvasAddonConstructor();
        this._canvasAddon = ( new Addon());
        this._disposeOfWebglRenderer();
        try {
            this.raw.loadAddon(this._canvasAddon);
            this._logService.trace('Canvas renderer was loaded');
        }
        catch (e) {
            this._logService.warn(`Canvas renderer could not be loaded, falling back to dom renderer`, e);
            const neverMeasureRenderTime = this._storageService.getBoolean("terminal.integrated.neverMeasureRenderTime" , -1 , false);
            if (!neverMeasureRenderTime && this._configHelper.config.gpuAcceleration !== 'off') {
                this._measureRenderTime();
            }
            XtermTerminal_1._suggestedRendererType = 'dom';
            this._disposeOfCanvasRenderer();
        }
        this._refreshImageAddon();
    }
    async _getCanvasAddonConstructor() {
        if (!CanvasAddon) {
            CanvasAddon = (await import('@xterm/addon-canvas').then(module => module.default ?? module)).CanvasAddon;
        }
        return CanvasAddon;
    }
    async _refreshImageAddon() {
        if (this._configHelper.config.enableImages && (this._canvasAddon || this._webglAddon)) {
            if (!this._imageAddon) {
                const AddonCtor = await this._getImageAddonConstructor();
                this._imageAddon = ( new AddonCtor());
                this.raw.loadAddon(this._imageAddon);
            }
        }
        else {
            try {
                this._imageAddon?.dispose();
            }
            catch {
            }
            this._imageAddon = undefined;
        }
    }
    async _getImageAddonConstructor() {
        if (!ImageAddon) {
            ImageAddon = (await import('@xterm/addon-image').then(module => module.default ?? module)).ImageAddon;
        }
        return ImageAddon;
    }
    async _getSearchAddonConstructor() {
        if (!SearchAddon) {
            SearchAddon = (await import('@xterm/addon-search').then(module => module.default ?? module)).SearchAddon;
        }
        return SearchAddon;
    }
    async _getUnicode11Constructor() {
        if (!Unicode11Addon) {
            Unicode11Addon = (await import('@xterm/addon-unicode11').then(module => module.default ?? module)).Unicode11Addon;
        }
        return Unicode11Addon;
    }
    async _getWebglAddonConstructor() {
        if (!WebglAddon) {
            WebglAddon = (await import('@xterm/addon-webgl').then(module => module.default ?? module)).WebglAddon;
        }
        return WebglAddon;
    }
    async _getSerializeAddonConstructor() {
        if (!SerializeAddon) {
            SerializeAddon = (await import('@xterm/addon-serialize').then(module => module.default ?? module)).SerializeAddon;
        }
        return SerializeAddon;
    }
    _disposeOfCanvasRenderer() {
        try {
            this._canvasAddon?.dispose();
        }
        catch {
        }
        this._canvasAddon = undefined;
        this._refreshImageAddon();
    }
    _disposeOfWebglRenderer() {
        try {
            this._webglAddon?.dispose();
        }
        catch {
        }
        this._webglAddon = undefined;
        this._refreshImageAddon();
    }
    async _measureRenderTime() {
        const frameTimes = [];
        if (!this._core._renderService?._renderer.value?._renderLayers) {
            return;
        }
        const textRenderLayer = this._core._renderService._renderer.value._renderLayers[0];
        const originalOnGridChanged = textRenderLayer?.onGridChanged;
        const evaluateCanvasRenderer = () => {
            frameTimes.shift();
            const medianTime = frameTimes.sort((a, b) => a - b)[Math.floor(frameTimes.length / 2)];
            if (medianTime > 50 ) {
                if (this._configHelper.config.gpuAcceleration === 'auto') {
                    XtermTerminal_1._suggestedRendererType = 'dom';
                    this.updateConfig();
                }
                else {
                    const promptChoices = [
                        {
                            label: ( localizeWithPath('vs/workbench/contrib/terminal/browser/xterm/xtermTerminal', 'yes', "Yes")),
                            run: () => this._configurationService.updateValue("terminal.integrated.gpuAcceleration" , 'off', 2 )
                        },
                        {
                            label: ( localizeWithPath('vs/workbench/contrib/terminal/browser/xterm/xtermTerminal', 'no', "No")),
                            run: () => { }
                        },
                        {
                            label: ( localizeWithPath(
                                'vs/workbench/contrib/terminal/browser/xterm/xtermTerminal',
                                'dontShowAgain',
                                "Don't Show Again"
                            )),
                            isSecondary: true,
                            run: () => this._storageService.store("terminal.integrated.neverMeasureRenderTime" , true, -1 , 1 )
                        }
                    ];
                    this._notificationService.prompt(Severity.Warning, ( localizeWithPath(
                        'vs/workbench/contrib/terminal/browser/xterm/xtermTerminal',
                        'terminal.slowRendering',
                        'Terminal GPU acceleration appears to be slow on your computer. Would you like to switch to disable it which may improve performance? [Read more about terminal settings](https://code.visualstudio.com/docs/editor/integrated-terminal#_changing-how-the-terminal-is-rendered).'
                    )), promptChoices);
                }
            }
        };
        textRenderLayer.onGridChanged = (terminal, firstRow, lastRow) => {
            const startTime = performance.now();
            originalOnGridChanged.call(textRenderLayer, terminal, firstRow, lastRow);
            frameTimes.push(performance.now() - startTime);
            if (frameTimes.length === 20 ) {
                evaluateCanvasRenderer();
                textRenderLayer.onGridChanged = originalOnGridChanged;
            }
        };
    }
    getXtermTheme(theme) {
        if (!theme) {
            theme = this._themeService.getColorTheme();
        }
        const foregroundColor = theme.getColor(TERMINAL_FOREGROUND_COLOR);
        const backgroundColor = this._xtermColorProvider.getBackgroundColor(theme);
        const cursorColor = theme.getColor(TERMINAL_CURSOR_FOREGROUND_COLOR) || foregroundColor;
        const cursorAccentColor = theme.getColor(TERMINAL_CURSOR_BACKGROUND_COLOR) || backgroundColor;
        const selectionBackgroundColor = theme.getColor(TERMINAL_SELECTION_BACKGROUND_COLOR);
        const selectionInactiveBackgroundColor = theme.getColor(TERMINAL_INACTIVE_SELECTION_BACKGROUND_COLOR);
        const selectionForegroundColor = theme.getColor(TERMINAL_SELECTION_FOREGROUND_COLOR) || undefined;
        return {
            background: backgroundColor?.toString(),
            foreground: foregroundColor?.toString(),
            cursor: cursorColor?.toString(),
            cursorAccent: cursorAccentColor?.toString(),
            selectionBackground: selectionBackgroundColor?.toString(),
            selectionInactiveBackground: selectionInactiveBackgroundColor?.toString(),
            selectionForeground: selectionForegroundColor?.toString(),
            black: theme.getColor(ansiColorIdentifiers[0])?.toString(),
            red: theme.getColor(ansiColorIdentifiers[1])?.toString(),
            green: theme.getColor(ansiColorIdentifiers[2])?.toString(),
            yellow: theme.getColor(ansiColorIdentifiers[3])?.toString(),
            blue: theme.getColor(ansiColorIdentifiers[4])?.toString(),
            magenta: theme.getColor(ansiColorIdentifiers[5])?.toString(),
            cyan: theme.getColor(ansiColorIdentifiers[6])?.toString(),
            white: theme.getColor(ansiColorIdentifiers[7])?.toString(),
            brightBlack: theme.getColor(ansiColorIdentifiers[8])?.toString(),
            brightRed: theme.getColor(ansiColorIdentifiers[9])?.toString(),
            brightGreen: theme.getColor(ansiColorIdentifiers[10])?.toString(),
            brightYellow: theme.getColor(ansiColorIdentifiers[11])?.toString(),
            brightBlue: theme.getColor(ansiColorIdentifiers[12])?.toString(),
            brightMagenta: theme.getColor(ansiColorIdentifiers[13])?.toString(),
            brightCyan: theme.getColor(ansiColorIdentifiers[14])?.toString(),
            brightWhite: theme.getColor(ansiColorIdentifiers[15])?.toString()
        };
    }
    _updateTheme(theme) {
        this.raw.options.theme = this.getXtermTheme(theme);
    }
    refresh() {
        this._updateTheme();
        this._decorationAddon.refreshLayouts();
    }
    async _updateUnicodeVersion() {
        if (!this._unicode11Addon && this._configHelper.config.unicodeVersion === '11') {
            const Addon = await this._getUnicode11Constructor();
            this._unicode11Addon = ( new Addon());
            this.raw.loadAddon(this._unicode11Addon);
        }
        if (this.raw.unicode.activeVersion !== this._configHelper.config.unicodeVersion) {
            this.raw.unicode.activeVersion = this._configHelper.config.unicodeVersion;
        }
    }
    _writeText(data) {
        this.raw.write(data);
    }
    dispose() {
        this._anyTerminalFocusContextKey.reset();
        this._anyFocusedTerminalHasSelection.reset();
        this._onDidDispose.fire();
        super.dispose();
    }
};
XtermTerminal.__decorator = ( __decorate([
    debounce(100)
], XtermTerminal.prototype, "_refreshImageAddon", null));
XtermTerminal = XtermTerminal_1 = ( __decorate([
    ( __param(8, IConfigurationService)),
    ( __param(9, IInstantiationService)),
    ( __param(10, ITerminalLogService)),
    ( __param(11, INotificationService)),
    ( __param(12, IStorageService)),
    ( __param(13, IThemeService)),
    ( __param(14, ITelemetryService)),
    ( __param(15, IClipboardService)),
    ( __param(16, IContextKeyService)),
    ( __param(17, IAccessibilitySignalService)),
    ( __param(18, ILayoutService))
], XtermTerminal));
function getXtermScaledDimensions(w, font, width, height) {
    if (!font.charWidth || !font.charHeight) {
        return null;
    }
    const scaledWidthAvailable = width * w.devicePixelRatio;
    const scaledCharWidth = font.charWidth * w.devicePixelRatio + font.letterSpacing;
    const cols = Math.max(Math.floor(scaledWidthAvailable / scaledCharWidth), 1);
    const scaledHeightAvailable = height * w.devicePixelRatio;
    const scaledCharHeight = Math.ceil(font.charHeight * w.devicePixelRatio);
    const scaledLineHeight = Math.floor(scaledCharHeight * font.lineHeight);
    const rows = Math.max(Math.floor(scaledHeightAvailable / scaledLineHeight), 1);
    return { rows, cols };
}
function vscodeToXtermLogLevel(logLevel) {
    switch (logLevel) {
        case LogLevel.Trace: return 'trace';
        case LogLevel.Debug: return 'debug';
        case LogLevel.Info: return 'info';
        case LogLevel.Warning: return 'warn';
        case LogLevel.Error: return 'error';
        default: return 'off';
    }
}
function vscodeToXtermCursorStyle(style) {
    if (style === 'line') {
        return 'bar';
    }
    return style;
}
export { XtermTerminal, getXtermScaledDimensions };
