
import { __decorate, __param } from '../../../../../../../../external/tslib/tslib.es6.js';
import { AsyncIterableObject } from '../../../../../base/common/async.js';
import { Range } from '../../../../common/core/range.js';
import { ColorDetector } from '../colorDetector.js';
import { ColorPickerWidget } from '../colorPickerWidget.js';
import { HoverAnchorType, RenderedHoverParts } from '../../../hover/browser/hoverTypes.js';
import { IThemeService } from '../../../../../platform/theme/common/themeService.service.js';
import { localize } from '../../../../../nls.js';
import { createColorHover, ColorPickerWidgetType, updateColorPresentations, updateEditorModel } from '../colorPickerParticipantUtils.js';
import { EditorOption } from '../../../../common/config/editorOptions.js';
import { Dimension } from '../../../../../base/browser/dom.js';
import { DisposableStore } from '../../../../../base/common/lifecycle.js';
import { HoverStartSource } from '../../../hover/browser/hoverOperation.js';

class ColorHover {
    constructor(owner, range, model, provider) {
        this.owner = owner;
        this.range = range;
        this.model = model;
        this.provider = provider;
        this.forceShowAtRange = true;
    }
    isValidForHoverAnchor(anchor) {
        return (anchor.type === HoverAnchorType.Range
            && this.range.startColumn <= anchor.range.startColumn
            && this.range.endColumn >= anchor.range.endColumn);
    }
    static fromBaseColor(owner, color) {
        return ( new ColorHover(owner, color.range, color.model, color.provider));
    }
}
let HoverColorPickerParticipant = class HoverColorPickerParticipant {
    constructor(_editor, _themeService) {
        this._editor = _editor;
        this._themeService = _themeService;
        this.hoverOrdinal = 2;
    }
    computeSync(_anchor, _lineDecorations, source) {
        return [];
    }
    computeAsync(anchor, lineDecorations, source, token) {
        return AsyncIterableObject.fromPromise(this._computeAsync(anchor, lineDecorations, source));
    }
    async _computeAsync(_anchor, lineDecorations, source) {
        if (!this._editor.hasModel()) {
            return [];
        }
        if (!this._isValidRequest(source)) {
            return [];
        }
        const colorDetector = ColorDetector.get(this._editor);
        if (!colorDetector) {
            return [];
        }
        for (const d of lineDecorations) {
            if (!colorDetector.isColorDecoration(d)) {
                continue;
            }
            const colorData = colorDetector.getColorData(d.range.getStartPosition());
            if (colorData) {
                const colorHover = ColorHover.fromBaseColor(this, await createColorHover(this._editor.getModel(), colorData.colorInfo, colorData.provider));
                return [colorHover];
            }
        }
        return [];
    }
    _isValidRequest(source) {
        const decoratorActivatedOn = this._editor.getOption(EditorOption.colorDecoratorsActivatedOn);
        switch (source) {
            case HoverStartSource.Mouse:
                return decoratorActivatedOn === 'hover' || decoratorActivatedOn === 'clickAndHover';
            case HoverStartSource.Click:
                return decoratorActivatedOn === 'click' || decoratorActivatedOn === 'clickAndHover';
            case HoverStartSource.Keyboard:
                return true;
        }
    }
    renderHoverParts(context, hoverParts) {
        const editor = this._editor;
        if (hoverParts.length === 0 || !editor.hasModel()) {
            return ( new RenderedHoverParts([]));
        }
        if (context.setMinimumDimensions) {
            const minimumHeight = editor.getOption(EditorOption.lineHeight) + 8;
            context.setMinimumDimensions(( new Dimension(302, minimumHeight)));
        }
        const disposables = ( new DisposableStore());
        const colorHover = hoverParts[0];
        const editorModel = editor.getModel();
        const model = colorHover.model;
        this._colorPicker = disposables.add(( new ColorPickerWidget(
            context.fragment,
            model,
            editor.getOption(EditorOption.pixelRatio),
            this._themeService,
            ColorPickerWidgetType.Hover
        )));
        let editorUpdatedByColorPicker = false;
        let range = ( new Range(
            colorHover.range.startLineNumber,
            colorHover.range.startColumn,
            colorHover.range.endLineNumber,
            colorHover.range.endColumn
        ));
        disposables.add(model.onColorFlushed(async (color) => {
            await updateColorPresentations(editorModel, model, color, range, colorHover);
            editorUpdatedByColorPicker = true;
            range = updateEditorModel(editor, range, model);
        }));
        disposables.add(model.onDidChangeColor((color) => {
            updateColorPresentations(editorModel, model, color, range, colorHover);
        }));
        disposables.add(editor.onDidChangeModelContent((e) => {
            if (editorUpdatedByColorPicker) {
                editorUpdatedByColorPicker = false;
            }
            else {
                context.hide();
                editor.focus();
            }
        }));
        const renderedHoverPart = {
            hoverPart: ColorHover.fromBaseColor(this, colorHover),
            hoverElement: this._colorPicker.domNode,
            dispose() { disposables.dispose(); }
        };
        return ( new RenderedHoverParts([renderedHoverPart]));
    }
    getAccessibleContent(hoverPart) {
        return localize(902, 'There is a color picker here.');
    }
    handleResize() {
        this._colorPicker?.layout();
    }
    handleHide() {
        this._colorPicker?.dispose();
        this._colorPicker = undefined;
    }
    isColorPickerVisible() {
        return !!this._colorPicker;
    }
};
HoverColorPickerParticipant = ( __decorate([
    ( __param(1, IThemeService))
], HoverColorPickerParticipant));

export { ColorHover, HoverColorPickerParticipant };
