
import { __decorate, __param } from '../../../../../../../../external/tslib/tslib.es6.js';
import { createElement, getWindow, addStandardDisposableListener, EventType, runAtThisOrScheduleAtNextAnimationFrame } from '../../../../../base/browser/dom.js';
import { createFastDomNode } from '../../../../../base/browser/fastDomNode.js';
import { PixelRatio } from '../../../../../base/browser/pixelRatio.js';
import { Color } from '../../../../../base/common/color.js';
import { DisposableStore } from '../../../../../base/common/lifecycle.js';
import '../../../../../platform/theme/common/colorUtils.js';
import '../../../../../platform/theme/common/colors/baseColors.js';
import '../../../../../platform/theme/common/colors/chartsColors.js';
import { diffOverviewRulerInserted, defaultInsertColor, diffInserted, diffOverviewRulerRemoved, defaultRemoveColor, diffRemoved } from '../../../../../platform/theme/common/colors/editorColors.js';
import '../../../../../platform/theme/common/colors/inputColors.js';
import '../../../../../platform/theme/common/colors/listColors.js';
import '../../../../../platform/theme/common/colors/menuColors.js';
import '../../../../../platform/theme/common/colors/minimapColors.js';
import '../../../../../platform/theme/common/colors/miscColors.js';
import '../../../../../platform/theme/common/colors/quickpickColors.js';
import '../../../../../platform/theme/common/colors/searchColors.js';
import { Themable } from '../../../../../platform/theme/common/themeService.js';
import { IThemeService } from '../../../../../platform/theme/common/themeService.service.js';

const MINIMUM_SLIDER_SIZE = 20;
let NotebookDiffOverviewRuler = class NotebookDiffOverviewRuler extends Themable {
    constructor(notebookEditor, width, container, themeService) {
        super(themeService);
        this.notebookEditor = notebookEditor;
        this.width = width;
        this._diffElementViewModels = [];
        this._lanes = 2;
        this._insertColor = null;
        this._removeColor = null;
        this._insertColorHex = null;
        this._removeColorHex = null;
        this._disposables = this._register(( new DisposableStore()));
        this._renderAnimationFrame = null;
        this._domNode = createFastDomNode(createElement("canvas"));
        this._domNode.setPosition("relative");
        this._domNode.setLayerHinting(true);
        this._domNode.setContain("strict");
        container.appendChild(this._domNode.domNode);
        this._overviewViewportDomElement = createFastDomNode(createElement("div"));
        this._overviewViewportDomElement.setClassName("diffViewport");
        this._overviewViewportDomElement.setPosition("absolute");
        this._overviewViewportDomElement.setWidth(width);
        container.appendChild(this._overviewViewportDomElement.domNode);
        this._register(
            PixelRatio.getInstance(getWindow(this._domNode.domNode)).onDidChange(() => {
                this._scheduleRender();
            })
        );
        this._register(this.themeService.onDidColorThemeChange(e => {
            const colorChanged = this.applyColors(e);
            if (colorChanged) {
                this._scheduleRender();
            }
        }));
        this.applyColors(this.themeService.getColorTheme());
        this._register(this.notebookEditor.onDidScroll(() => {
            this._renderOverviewViewport();
        }));
        this._register(
            addStandardDisposableListener(container, EventType.POINTER_DOWN, e => {
                this.notebookEditor.delegateVerticalScrollbarPointerDown(e);
            })
        );
    }
    applyColors(theme) {
        const newInsertColor = theme.getColor(diffOverviewRulerInserted) || ( (theme.getColor(diffInserted) || defaultInsertColor).transparent(2));
        const newRemoveColor = theme.getColor(diffOverviewRulerRemoved) || ( (theme.getColor(diffRemoved) || defaultRemoveColor).transparent(2));
        const hasChanges = !newInsertColor.equals(this._insertColor) || !newRemoveColor.equals(this._removeColor);
        this._insertColor = newInsertColor;
        this._removeColor = newRemoveColor;
        if (this._insertColor) {
            this._insertColorHex = Color.Format.CSS.formatHexA(this._insertColor);
        }
        if (this._removeColor) {
            this._removeColorHex = Color.Format.CSS.formatHexA(this._removeColor);
        }
        return hasChanges;
    }
    layout() {
        this._layoutNow();
    }
    updateViewModels(elements, eventDispatcher) {
        this._disposables.clear();
        this._diffElementViewModels = elements;
        if (eventDispatcher) {
            this._disposables.add(eventDispatcher.onDidChangeLayout(() => {
                this._scheduleRender();
            }));
            this._disposables.add(eventDispatcher.onDidChangeCellLayout(() => {
                this._scheduleRender();
            }));
        }
        this._scheduleRender();
    }
    _scheduleRender() {
        if (this._renderAnimationFrame === null) {
            this._renderAnimationFrame = runAtThisOrScheduleAtNextAnimationFrame(
                getWindow(this._domNode.domNode),
                this._onRenderScheduled.bind(this),
                16
            );
        }
    }
    _onRenderScheduled() {
        this._renderAnimationFrame = null;
        this._layoutNow();
    }
    _layoutNow() {
        const layoutInfo = this.notebookEditor.getLayoutInfo();
        const height = layoutInfo.height;
        const contentHeight = ( this._diffElementViewModels.map(view => view.totalHeight)).reduce((a, b) => a + b, 0);
        const ratio = PixelRatio.getInstance(getWindow(this._domNode.domNode)).value;
        this._domNode.setWidth(this.width);
        this._domNode.setHeight(height);
        this._domNode.domNode.width = this.width * ratio;
        this._domNode.domNode.height = height * ratio;
        const ctx = this._domNode.domNode.getContext("2d");
        ctx.clearRect(0, 0, this.width * ratio, height * ratio);
        this._renderCanvas(ctx, this.width * ratio, height * ratio, contentHeight * ratio, ratio);
        this._renderOverviewViewport();
    }
    _renderOverviewViewport() {
        const layout = this._computeOverviewViewport();
        if (!layout) {
            this._overviewViewportDomElement.setTop(0);
            this._overviewViewportDomElement.setHeight(0);
        } else {
            this._overviewViewportDomElement.setTop(layout.top);
            this._overviewViewportDomElement.setHeight(layout.height);
        }
    }
    _computeOverviewViewport() {
        const layoutInfo = this.notebookEditor.getLayoutInfo();
        if (!layoutInfo) {
            return null;
        }
        const scrollTop = this.notebookEditor.getScrollTop();
        const scrollHeight = this.notebookEditor.getScrollHeight();
        const computedAvailableSize = Math.max(0, layoutInfo.height);
        const computedRepresentableSize = Math.max(0, computedAvailableSize - 2 * 0);
        const visibleSize = layoutInfo.height;
        const computedSliderSize = Math.round(Math.max(
            MINIMUM_SLIDER_SIZE,
            Math.floor(visibleSize * computedRepresentableSize / scrollHeight)
        ));
        const computedSliderRatio = (computedRepresentableSize - computedSliderSize) / (scrollHeight - visibleSize);
        const computedSliderPosition = Math.round(scrollTop * computedSliderRatio);
        return {
            height: computedSliderSize,
            top: computedSliderPosition
        };
    }
    _renderCanvas(ctx, width, height, scrollHeight, ratio) {
        if (!this._insertColorHex || !this._removeColorHex) {
            return;
        }
        const laneWidth = width / this._lanes;
        let currentFrom = 0;
        for (let i = 0; i < this._diffElementViewModels.length; i++) {
            const element = this._diffElementViewModels[i];
            const cellHeight = Math.round((element.totalHeight / scrollHeight) * ratio * height);
            switch (element.type) {
            case "insert":
                ctx.fillStyle = this._insertColorHex;
                ctx.fillRect(laneWidth, currentFrom, laneWidth, cellHeight);
                break;
            case "delete":
                ctx.fillStyle = this._removeColorHex;
                ctx.fillRect(0, currentFrom, laneWidth, cellHeight);
                break;
            case "unchanged":
            case "unchangedMetadata":
                break;
            case "modified":
            case "modifiedMetadata":
                ctx.fillStyle = this._removeColorHex;
                ctx.fillRect(0, currentFrom, laneWidth, cellHeight);
                ctx.fillStyle = this._insertColorHex;
                ctx.fillRect(laneWidth, currentFrom, laneWidth, cellHeight);
                break;
            }
            currentFrom += cellHeight;
        }
    }
    dispose() {
        if (this._renderAnimationFrame !== null) {
            this._renderAnimationFrame.dispose();
            this._renderAnimationFrame = null;
        }
        super.dispose();
    }
};
NotebookDiffOverviewRuler = ( __decorate([( __param(3, IThemeService))], NotebookDiffOverviewRuler));

export { NotebookDiffOverviewRuler };
