"use strict";
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
    if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
        if (ar || !(i in from)) {
            if (!ar) ar = Array.prototype.slice.call(from, 0, i);
            ar[i] = from[i];
        }
    }
    return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SciChartRenderer = void 0;
var Rect_1 = require("../../Core/Rect");
var AutoRange_1 = require("../../types/AutoRange");
var DefaultRenderLayer_1 = require("../../types/DefaultRenderLayer");
var WebGlRenderContext2D_1 = require("../Drawing/WebGlRenderContext2D");
var SciChartSurface_1 = require("../Visuals/SciChartSurface");
var SciChartSurfaceBase_1 = require("../Visuals/SciChartSurfaceBase");
var DpiHelper_1 = require("../Visuals/TextureManager/DpiHelper");
var RenderPassData_1 = require("./RenderPassData");
var RenderPassInfo_1 = require("./RenderPassInfo");
var NativeObject_1 = require("../Visuals/Helpers/NativeObject");
var createNativeRect_1 = require("../Visuals/Helpers/createNativeRect");
var parseColor_1 = require("../../utils/parseColor");
var logger_1 = require("../../utils/logger");
var performance_1 = require("../../utils/performance");
var ExtremeResamplerHelper_1 = require("../Numerics/Resamplers/ExtremeResamplerHelper");
var ModifierType_1 = require("../../types/ModifierType");
var translate_1 = require("../../utils/translate");
var watermarkHelpers_1 = require("../../utils/watermarkHelpers");
var Thickness_1 = require("../../Core/Thickness");
var OrderedRenderable_1 = require("../../types/OrderedRenderable");
/**
 * A class used internally in SciChart to perform layout, arrangement, data-preparation and rendering on the Cartesian 2D {@link SciChartSurface}
 */
var SciChartRenderer = /** @class */ (function () {
    /**
     * Creates an instance of the SciChartRenderer
     * @param sciChartSurface The {@link SciChartSurface} that we are rendering
     */
    function SciChartRenderer(sciChartSurface) {
        this.isInvalidated = false;
        /**
         * Used internally to track requestAnimationFrame for svg rendering.
         * When `undefined` there is no pending RAF.
         */
        this.svgRenderRequestId = undefined;
        this.domRenderRun = false;
        this.sciChartSurface = sciChartSurface;
    }
    SciChartRenderer.prototype.renderDomOnly = function () {
        var _this = this;
        var _a;
        if (this.sciChartSurface.isDeleted) {
            return;
        }
        logger_1.Logger.debug("svg only render start");
        this.domRenderRun = true;
        this.sciChartSurface.preRender.raiseEvent(undefined);
        // Animation Step
        var timeElapsed = this.previousTime ? Date.now() - this.previousTime : 0;
        this.previousTime = Date.now();
        // Not worried about the apparent duplication here as we prevent animations running in full render if they have run here.
        var animationStartMark = performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.GenericAnimationStart, {
            contextId: this.sciChartSurface.id,
            level: performance_1.EPerformanceDebugLevel.Verbose
        });
        this.sciChartSurface.onAnimate(timeElapsed);
        this.sciChartSurface.genericAnimationsRun.raiseEvent();
        this.domRenderRun = true;
        performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.GenericAnimationEnd, {
            contextId: this.sciChartSurface.id,
            relatedId: (_a = animationStartMark === null || animationStartMark === void 0 ? void 0 : animationStartMark.detail) === null || _a === void 0 ? void 0 : _a.relatedId,
            level: performance_1.EPerformanceDebugLevel.Verbose
        });
        this.sciChartSurface.layoutMeasured.raiseEvent();
        if (this.isInvalidated) {
            logger_1.Logger.debug("main chart invalidated during dom prerender.  Reverting to full render");
            this.sciChartSurface.webAssemblyContext2D.TSRRequestDraw();
            return;
        }
        var userAnnotations = this.sciChartSurface.annotations.asArray();
        var modifierAnnotations = this.sciChartSurface.modifierAnnotations.asArray();
        var annotations = __spreadArray(__spreadArray([], userAnnotations, true), modifierAnnotations, true);
        var svgAnnotations = annotations.filter(function (an) { return an.isDomAnnotation; });
        if (svgAnnotations.length > 0) {
            this.drawSvgAnnotations(svgAnnotations, this.sciChartSurface.getCoordSvgTranslation());
        }
        this.sciChartSurface.rendered.raiseEvent(false);
        this.domRenderRun = false;
        // Invalidate for the animations
        if (this.sciChartSurface.isRunningAnimation) {
            setTimeout(function () { return _this.sciChartSurface.invalidateElement({ svgOnly: true }); }, 0);
        }
        logger_1.Logger.debug("dom only render end");
    };
    /**
     * Render loop for the current {@SciChartSurface}
     * @param renderContext the {@WebGLRenderContext2D} used for drawing
     */
    SciChartRenderer.prototype.render = function (renderContext) {
        var _this = this;
        var _a, _b, _c, _d, _e, _f, _g, _h;
        if (this.sciChartSurface.isDeleted) {
            return;
        }
        if (this.sciChartSurface.hasInvalidState) {
            this.displayErrorMessage();
            return;
        }
        var renderStartMark = performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.RenderStart, {
            contextId: this.sciChartSurface.id,
            level: performance_1.EPerformanceDebugLevel.Verbose
        });
        logger_1.Logger.debug("render start");
        var nativeContext = renderContext.getNativeContext();
        var wasmContext = this.sciChartSurface.webAssemblyContext2D;
        // Step 1 validate the chart and show errors
        this.validate();
        if (!this.domRenderRun) {
            // Animation Step
            var timeElapsed = this.previousTime ? Date.now() - this.previousTime : 0;
            this.previousTime = Date.now();
            var animationStartMark = performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.GenericAnimationStart, {
                contextId: this.sciChartSurface.id,
                level: performance_1.EPerformanceDebugLevel.Verbose
            });
            // allow animations to cause invalidation
            this.isInvalidated = false;
            this.sciChartSurface.onAnimate(timeElapsed);
            this.sciChartSurface.genericAnimationsRun.raiseEvent();
            // block further invalidations
            this.isInvalidated = true;
            performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.GenericAnimationEnd, {
                contextId: this.sciChartSurface.id,
                relatedId: (_a = animationStartMark === null || animationStartMark === void 0 ? void 0 : animationStartMark.detail) === null || _a === void 0 ? void 0 : _a.relatedId,
                level: performance_1.EPerformanceDebugLevel.Verbose
            });
        }
        // Step 2 autorange x
        this.sciChartSurface.updateStackedCollectionAccumulatedVectors();
        var autoRangeStartMark = performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.AutoRangeStart, {
            contextId: this.sciChartSurface.id,
            level: performance_1.EPerformanceDebugLevel.Verbose
        });
        this.sciChartSurface.xAxes.asArray().forEach(function (axis) { return _this.tryPerformAutoRangeOn(axis, _this.sciChartSurface); });
        // Step 3 prepare render data
        var viewRect = (_b = this.sciChartSurface.seriesViewRect) !== null && _b !== void 0 ? _b : Rect_1.Rect.create(0, 0, renderContext.viewportSize.width, renderContext.viewportSize.height);
        var renderPassInfo = this.prepareSeriesRenderData(viewRect);
        // Step 4 autorange y using resampled data if available.
        this.sciChartSurface.yAxes.asArray().forEach(function (axis) { return _this.tryPerformAutoRangeOn(axis, _this.sciChartSurface); });
        performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.AutoRangeEnd, {
            contextId: this.sciChartSurface.id,
            relatedId: (_c = autoRangeStartMark === null || autoRangeStartMark === void 0 ? void 0 : autoRangeStartMark.detail) === null || _c === void 0 ? void 0 : _c.relatedId,
            level: performance_1.EPerformanceDebugLevel.Verbose
        });
        // Step 3 layout
        var layoutStartMark = performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.LayoutStart, {
            contextId: this.sciChartSurface.id,
            level: performance_1.EPerformanceDebugLevel.Verbose
        });
        if (SciChartSurface_1.SciChartSurface.isSubSurface(this.sciChartSurface)) {
            this.sciChartSurface.updateSubLayout();
        }
        var titleOffset = this.measureTitle(renderContext);
        var layoutOffset = Thickness_1.Thickness.mergeAdd((_d = this.sciChartSurface.offset) !== null && _d !== void 0 ? _d : Thickness_1.Thickness.fromNumber(0), titleOffset);
        var seriesViewRect = this.sciChartSurface.layoutManager.layoutChart(renderContext.viewportSize, layoutOffset);
        this.sciChartSurface.setCoordSvgTranslation(seriesViewRect.x, seriesViewRect.y);
        this.resizeAnnotationRootElements(seriesViewRect);
        // Initialise axes coordinate calculators.  Must happen after layout.
        this.prepareAxesRenderData();
        renderContext.enqueueLayeredDraw(function () {
            // renderContext.SetTranslation(0, 0);
            _this.sciChartSurface.updateBackground(renderContext);
        }, this.getAbsoluteLayer(DefaultRenderLayer_1.EDefaultRenderLayer.Background));
        this.layoutTitle(seriesViewRect);
        this.scheduleTitleDraw(renderContext);
        performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.LayoutEnd, {
            contextId: this.sciChartSurface.id,
            relatedId: (_e = layoutStartMark === null || layoutStartMark === void 0 ? void 0 : layoutStartMark.detail) === null || _e === void 0 ? void 0 : _e.relatedId,
            level: performance_1.EPerformanceDebugLevel.Verbose
        });
        if (!this.sciChartSurface.isSubSurface) {
            this.sciChartSurface.chartModifiers.asArray().forEach(function (cm) {
                if (cm.modifierType !== ModifierType_1.EModifierType.Chart3DModifier) {
                    cm.linkAxes();
                }
                cm.onParentSurfaceLayoutComplete();
            });
        }
        (_f = this.sciChartSurface.subCharts) === null || _f === void 0 ? void 0 : _f.forEach(function (sc) {
            if (sc.hasInvalidState)
                return;
            sc.chartModifiers.asArray().forEach(function (cm) {
                cm.onParentSurfaceLayoutComplete();
            });
        });
        if (!this.domRenderRun) {
            this.sciChartSurface.layoutMeasured.raiseEvent();
        }
        // Any invalidate after this will cause a rerender
        this.isInvalidated = false;
        this.domRenderRun = false;
        // Draw seriesViewRect border
        renderContext.enqueueLayeredDraw(function () {
            _this.sciChartSurface.drawBorder(renderContext);
        }, this.getAbsoluteLayer(DefaultRenderLayer_1.EDefaultRenderLayer.AxisBandsLayer));
        // Step 5 Draw X, Y axis and gridlines
        if (this.sciChartSurface.debugRendering) {
            this.drawDebugAxes(this.sciChartSurface, renderContext);
        }
        this.drawAxes(this.sciChartSurface, renderContext);
        // if useOrderedDrawing
        this.getSeriesDrawFunctions(this.sciChartSurface, renderPassInfo, renderContext);
        this.getAnnotationDrawFunctions(this.sciChartSurface, renderPassInfo, renderContext);
        // Further thought required here.  This could go weird if series specifices a later surfaceRenderOrder
        // Perform global text layout
        if (this.sciChartSurface.dataLabelLayoutManager) {
            var dataLabelLayout = new OrderedRenderable_1.OrderedRenderable(this.sciChartSurface.getSurfaceRenderOrder(), DefaultRenderLayer_1.EDefaultRenderLayer.AxesLayer, undefined);
            renderPassInfo.addRenderable(dataLabelLayout, function () {
                var _a;
                var mark = performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.PerformTextLayoutStart, {
                    contextId: _this.sciChartSurface.id,
                    level: performance_1.EPerformanceDebugLevel.Verbose
                });
                _this.sciChartSurface.dataLabelLayoutManager.performTextLayout(_this.sciChartSurface, renderPassInfo);
                performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.PerformTextLayoutEnd, {
                    contextId: _this.sciChartSurface.id,
                    relatedId: (_a = mark === null || mark === void 0 ? void 0 : mark.detail) === null || _a === void 0 ? void 0 : _a.relatedId,
                    level: performance_1.EPerformanceDebugLevel.Verbose
                });
            });
        }
        // Draw series text
        // This might need to be per series - or DataLabelProvider might need to implement IOrderedRenderable
        var dataLabels = new OrderedRenderable_1.OrderedRenderable(this.sciChartSurface.getSurfaceRenderOrder(), DefaultRenderLayer_1.EDefaultRenderLayer.AxesLayer, undefined);
        renderPassInfo.addRenderable(dataLabels, function () {
            renderPassInfo.renderableSeriesArray.forEach(function (rs, index) {
                var _a;
                if (rs.dataLabelProvider) {
                    var mark = performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.DrawDataLabelsStart, {
                        contextId: rs.id,
                        parentContextId: _this.sciChartSurface.id,
                        level: performance_1.EPerformanceDebugLevel.Verbose
                    });
                    rs.dataLabelProvider.draw(renderContext);
                    performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.DrawDataLabelsEnd, {
                        contextId: rs.id,
                        parentContextId: _this.sciChartSurface.id,
                        relatedId: (_a = mark === null || mark === void 0 ? void 0 : mark.detail) === null || _a === void 0 ? void 0 : _a.relatedId,
                        level: performance_1.EPerformanceDebugLevel.Verbose
                    });
                }
            });
        });
        // ENQUEUE RENDERABLES
        this.enqueueRenderables(renderContext, renderPassInfo);
        // enqueue final font rendering after everything else for this surface.
        renderContext.enqueueLayeredDraw(function () {
            var clipRect = _this.sciChartSurface.clipRect;
            renderContext.resetAndClip(clipRect);
            renderContext.endFonts();
        }, this.getAbsoluteLayer(DefaultRenderLayer_1.EDefaultRenderLayer.AxesLayer));
        renderContext.enqueueLayeredDraw(function () { }, this.getAbsoluteLayer(DefaultRenderLayer_1.EDefaultRenderLayer.Foreground));
        //old logic which we may make optional
        // Step 6 Draw annotations below the series
        // const userAnnotations = this.sciChartSurface.annotations.asArray();
        // const modifierAnnotations = this.sciChartSurface.modifierAnnotations.asArray();
        // const annotations = [...userAnnotations, ...modifierAnnotations];
        // const renderContextAnnotations = annotations.filter(el => !el.isDomAnnotation) as RenderContextAnnotationBase[];
        // // Draw annotations before axis
        // const annotationsLayerBelowAxis = this.getAbsoluteLayer(EDefaultRenderLayer.Background);
        // renderContext.enqueueLayeredDraw(() => {
        //     this.drawRenderContextAnnotations(
        //         renderContextAnnotations,
        //         EAnnotationLayer.Background,
        //         renderContext,
        //         seriesViewRect
        //     );
        // }, annotationsLayerBelowAxis);
        // const annotationsBelowLayer = this.getAbsoluteLayer(EDefaultRenderLayer.AnnotationsBelowSeriesLayer);
        // renderContext.enqueueLayeredDraw(() => {
        //     this.drawRenderContextAnnotations(
        //         renderContextAnnotations,
        //         EAnnotationLayer.BelowChart,
        //         renderContext,
        //         seriesViewRect
        //     );
        // }, annotationsBelowLayer);
        // const seriesLayer = this.getAbsoluteLayer(EDefaultRenderLayer.SeriesLayer);
        // // Step 7 Draw series. Queue series rendering after grid lines and bands, but before the axes
        // renderContext.enqueueLayeredDraw(
        //     () => this.drawSeries(this.sciChartSurface, renderPassInfo, renderContext),
        //     seriesLayer
        // );
        // const annotationsAboveLayer = this.getAbsoluteLayer(EDefaultRenderLayer.AnnotationsAboveSeriesLayer);
        // // Step 8 Draw annotations above the series
        // renderContext.enqueueLayeredDraw(() => {
        //     this.drawRenderContextAnnotations(
        //         renderContextAnnotations,
        //         EAnnotationLayer.AboveChart,
        //         renderContext,
        //         seriesViewRect
        //     );
        // }, annotationsAboveLayer);
        // // Step 8 Draw annotations above the series
        // const foregroundLayer = this.getAbsoluteLayer(EDefaultRenderLayer.Foreground);
        // renderContext.enqueueLayeredDraw(() => {
        //     const clipRect = this.sciChartSurface.clipRect;
        //     renderContext.SetClipRect(clipRect);
        //     renderContext.endFonts();
        // }, foregroundLayer);
        // // Execute rendering of queued elements
        // renderContext.drawLayers();
        // // Step 9 Draw SVG or Html Overlays
        // const htmlBasedAnnotations = annotations.filter(el => el.isDomAnnotation) as DomAnnotationBase[];
        // this.drawHtmlBasedAnnotations(htmlBasedAnnotations, this.sciChartSurface.getCoordSvgTranslation());
        // Execute rendering of queued elements
        renderContext.drawLayers();
        // Update watermark
        if (!SciChartSurface_1.SciChartSurface.isSubSurface(this.sciChartSurface)) {
            this.updateWatermark(renderContext, seriesViewRect);
        }
        else if (renderContext.doDraw) {
            this.updateWatermark(renderContext, this.sciChartSurface.parentSurface.seriesViewRect);
        }
        // Step 10 Call OnParentSurfaceRendered
        var postDrawActionsStartMark = performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.PostDrawActionsStart, {
            contextId: this.sciChartSurface.id,
            level: performance_1.EPerformanceDebugLevel.Verbose
        });
        this.onParentSurfaceRendered();
        // Invalidate for the animations
        if (this.sciChartSurface.isRunningAnimation && this.svgRenderRequestId === undefined) {
            setTimeout(this.sciChartSurface.invalidateElement, 0);
        }
        performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.PostDrawActionsEnd, {
            contextId: this.sciChartSurface.id,
            relatedId: (_g = postDrawActionsStartMark === null || postDrawActionsStartMark === void 0 ? void 0 : postDrawActionsStartMark.detail) === null || _g === void 0 ? void 0 : _g.relatedId,
            level: performance_1.EPerformanceDebugLevel.Verbose
        });
        performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.RenderEnd, {
            contextId: this.sciChartSurface.id,
            relatedId: (_h = renderStartMark === null || renderStartMark === void 0 ? void 0 : renderStartMark.detail) === null || _h === void 0 ? void 0 : _h.relatedId,
            level: performance_1.EPerformanceDebugLevel.Verbose
        });
        logger_1.Logger.debug("render end");
    };
    SciChartRenderer.prototype.getSeriesDrawFunctions = function (scs, renderPassInfo, renderContext) {
        var renderableSeriesArray = renderPassInfo.renderableSeriesArray;
        var viewRect = this.sciChartSurface.seriesViewRect;
        var clipRect = Rect_1.Rect.intersect(this.sciChartSurface.seriesViewRect, this.sciChartSurface.clipRect);
        var hasVerticalAxes = scs.xAxes.asArray().some(function (a) { return a.isVerticalChart; });
        var isFirstSeries = true;
        var _loop_1 = function (rs) {
            if (!rs.isVisible)
                return "continue";
            var drawFn = function () {
                if (hasVerticalAxes || renderPassInfo.hasOtherSeriesLayerRenderables) {
                    renderContext.setTranslationRotationAndClip(clipRect, viewRect.x, viewRect.y);
                }
                else {
                    // Performance optimization, we call the method only for the first renderable series
                    if (isFirstSeries) {
                        renderContext.setTranslationRotationAndClip(clipRect, viewRect.x, viewRect.y);
                    }
                }
                rs.draw(renderContext, rs.getCurrentRenderPassData());
                isFirstSeries = false;
            };
            renderPassInfo.addRenderable(rs, drawFn);
        };
        for (var _i = 0, renderableSeriesArray_1 = renderableSeriesArray; _i < renderableSeriesArray_1.length; _i++) {
            var rs = renderableSeriesArray_1[_i];
            _loop_1(rs);
        }
    };
    SciChartRenderer.prototype.getAnnotationDrawFunctions = function (scs, renderPassInfo, renderContext) {
        var seriesViewRect = this.sciChartSurface.seriesViewRect;
        var userAnnotations = this.sciChartSurface.annotations.asArray();
        var modifierAnnotations = this.sciChartSurface.modifierAnnotations.asArray();
        var coordSvgTranslation = this.sciChartSurface.getCoordSvgTranslation();
        for (var _i = 0, userAnnotations_1 = userAnnotations; _i < userAnnotations_1.length; _i++) {
            var annotation = userAnnotations_1[_i];
            if (annotation.isDomAnnotation) {
                this.getHTMLAnnotationDrawFunction(annotation, coordSvgTranslation);
            }
            else if (annotation.isVisible) {
                this.getRenderContextAnnotationDrawFunction(annotation, renderContext, seriesViewRect, renderPassInfo);
            }
        }
        for (var _a = 0, modifierAnnotations_1 = modifierAnnotations; _a < modifierAnnotations_1.length; _a++) {
            var annotation = modifierAnnotations_1[_a];
            if (annotation.isDomAnnotation) {
                this.getHTMLAnnotationDrawFunction(annotation, coordSvgTranslation);
            }
            else if (annotation.isVisible) {
                this.getRenderContextAnnotationDrawFunction(annotation, renderContext, seriesViewRect, renderPassInfo);
            }
        }
    };
    SciChartRenderer.prototype.getHTMLAnnotationDrawFunction = function (annotation, coordSvgTranslation) {
        var _a;
        annotation.linkAxes();
        var xAxis = annotation.xAxis;
        var yAxis = annotation.yAxis;
        if (!xAxis || !yAxis) {
            console.error("Cannot draw annotations before axes have been configured. Add axes first, or use suspendUpdates to pause drawing until axes are available.");
        }
        else {
            var mark = performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.DrawAnnotationStart, {
                contextId: annotation.id,
                parentContextId: this.sciChartSurface.id,
                level: performance_1.EPerformanceDebugLevel.Verbose
            });
            annotation.update(xAxis.getCurrentCoordinateCalculator(), yAxis.getCurrentCoordinateCalculator(), coordSvgTranslation.x / DpiHelper_1.DpiHelper.PIXEL_RATIO, coordSvgTranslation.y / DpiHelper_1.DpiHelper.PIXEL_RATIO);
            performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.DrawAnnotationEnd, {
                contextId: annotation.id,
                parentContextId: this.sciChartSurface.id,
                relatedId: (_a = mark === null || mark === void 0 ? void 0 : mark.detail) === null || _a === void 0 ? void 0 : _a.relatedId,
                level: performance_1.EPerformanceDebugLevel.Verbose
            });
        }
    };
    SciChartRenderer.prototype.getRenderContextAnnotationDrawFunction = function (annotation, renderContext, seriesViewRect, renderPassInfo) {
        var _this = this;
        var surfaceViewRect = this.sciChartSurface.viewRect;
        var chartViewRect = this.sciChartSurface.chartViewRect;
        if (annotation.isVisible) {
            var drawFn = function () {
                var _a, _b, _c;
                annotation.linkAxes();
                var xAxis = annotation.xAxis;
                var yAxis = annotation.yAxis;
                if (!xAxis || !yAxis) {
                    console.error("Cannot draw annotations before axes have been configured. Add axes first, or use suspendUpdates to pause drawing until axes are available.");
                }
                else if (!xAxis.parentSurface) {
                    console.error("Cannot draw annotation ".concat((_a = annotation === null || annotation === void 0 ? void 0 : annotation.constructor) === null || _a === void 0 ? void 0 : _a.name, " with X-axis detached from sciChartSurface. Set a correct xAxisId on the annotation."));
                }
                else if (!yAxis.parentSurface) {
                    console.error("Cannot draw annotation ".concat((_b = annotation === null || annotation === void 0 ? void 0 : annotation.constructor) === null || _b === void 0 ? void 0 : _b.name, " with Y-axis detached from sciChartSurface. Set a correct yAxisId on the annotation."));
                }
                else {
                    var mark = performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.DrawAnnotationStart, {
                        contextId: annotation.id,
                        parentContextId: _this.sciChartSurface.id,
                        level: performance_1.EPerformanceDebugLevel.Verbose
                    });
                    annotation.drawWithContext(renderContext, xAxis.getCurrentCoordinateCalculator(), yAxis.getCurrentCoordinateCalculator(), seriesViewRect, surfaceViewRect, chartViewRect);
                    performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.DrawAnnotationEnd, {
                        contextId: annotation.id,
                        parentContextId: _this.sciChartSurface.id,
                        relatedId: (_c = mark === null || mark === void 0 ? void 0 : mark.detail) === null || _c === void 0 ? void 0 : _c.relatedId,
                        level: performance_1.EPerformanceDebugLevel.Verbose
                    });
                }
            };
            renderPassInfo.addRenderable(annotation, drawFn);
        }
    };
    SciChartRenderer.prototype.enqueueRenderables = function (renderContext, renderPassInfo) {
        renderPassInfo.resolveNextTo();
        var surfaces = Array.from(renderPassInfo.rendermap.keys());
        surfaces.sort(function (a, b) { return a - b; });
        for (var _i = 0, surfaces_1 = surfaces; _i < surfaces_1.length; _i++) {
            var surfaceNum = surfaces_1[_i];
            var layers = Array.from(renderPassInfo.rendermap.get(surfaceNum).keys());
            layers.sort(function (a, b) { return a - b; });
            for (var _a = 0, layers_1 = layers; _a < layers_1.length; _a++) {
                var layerNum = layers_1[_a];
                var layer = renderPassInfo.rendermap.get(surfaceNum).get(layerNum);
                layer.sort(function (a, b) { return a.resolvedOrder - b.resolvedOrder; });
                var drawLayer = (0, WebGlRenderContext2D_1.calculateAbsoluteRenderLayer)(surfaceNum, this.sciChartSurface.stepBetweenLayers, layerNum);
                for (var _b = 0, layer_1 = layer; _b < layer_1.length; _b++) {
                    var item = layer_1[_b];
                    if (item === null || item === void 0 ? void 0 : item.drawFunction) {
                        this.enqueueRenderable(renderContext, item, drawLayer);
                    }
                }
            }
        }
    };
    SciChartRenderer.prototype.enqueueRenderable = function (renderContext, item, absoluteLayer) {
        renderContext.enqueueLayeredDraw(item.drawFunction, absoluteLayer);
    };
    SciChartRenderer.prototype.displayErrorMessage = function () {
        var errorDialog = document.createElement("div");
        errorDialog.style.width = "100%";
        errorDialog.style.height = "100%";
        errorDialog.style.color = "white";
        errorDialog.style.background = "black";
        errorDialog.style.display = "flex";
        errorDialog.style.justifyContent = "center";
        errorDialog.style.alignItems = "center";
        var errorMessage = document.createElement("span");
        errorMessage.innerText = "The surface with id ".concat(this.sciChartSurface.id, " has an invalid state. Check the console for errors.");
        errorDialog.appendChild(errorMessage);
        this.sciChartSurface.domDivContainer.style.background = "black";
        this.sciChartSurface.domDivContainer.appendChild(errorDialog);
    };
    SciChartRenderer.prototype.drawRenderContextAnnotations = function (annotations, annotationLayer, renderContext, seriesViewRect) {
        var _this = this;
        var surfaceViewRect = this.sciChartSurface.viewRect;
        var chartViewRect = this.sciChartSurface.chartViewRect;
        annotations
            .filter(function (a) { return a.annotationLayer === annotationLayer; })
            .forEach(function (a) {
            var _a;
            a.linkAxes();
            var xAxis = a.xAxis;
            var yAxis = a.yAxis;
            if (!xAxis || !yAxis) {
                console.error("Cannot draw annotations before axes have been configured. Add axes first, or use suspendUpdates to pause drawing until axes are available.");
            }
            else {
                if (!a.isHidden) {
                    var mark = performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.DrawAnnotationStart, {
                        contextId: a.id,
                        parentContextId: _this.sciChartSurface.id,
                        level: performance_1.EPerformanceDebugLevel.Verbose
                    });
                    a.drawWithContext(renderContext, xAxis.getCurrentCoordinateCalculator(), yAxis.getCurrentCoordinateCalculator(), seriesViewRect, surfaceViewRect, chartViewRect);
                    performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.DrawAnnotationEnd, {
                        contextId: a.id,
                        parentContextId: _this.sciChartSurface.id,
                        relatedId: (_a = mark === null || mark === void 0 ? void 0 : mark.detail) === null || _a === void 0 ? void 0 : _a.relatedId,
                        level: performance_1.EPerformanceDebugLevel.Verbose
                    });
                }
            }
        });
    };
    SciChartRenderer.prototype.drawHtmlBasedAnnotations = function (annotations, coordSvgTranslation) {
        var _this = this;
        annotations.forEach(function (a) {
            var _a;
            a.linkAxes();
            var xAxis = a.xAxis;
            var yAxis = a.yAxis;
            if (!xAxis || !yAxis) {
                console.error("Cannot draw annotations before axes have been configured. Add axes first, or use suspendUpdates to pause drawing until axes are available.");
            }
            else {
                var mark = performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.DrawAnnotationStart, {
                    contextId: _this.sciChartSurface.id,
                    level: performance_1.EPerformanceDebugLevel.Verbose
                });
                a.update(xAxis.getCurrentCoordinateCalculator(), yAxis.getCurrentCoordinateCalculator(), coordSvgTranslation.x / DpiHelper_1.DpiHelper.PIXEL_RATIO, coordSvgTranslation.y / DpiHelper_1.DpiHelper.PIXEL_RATIO);
                performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.DrawAnnotationEnd, {
                    contextId: _this.sciChartSurface.id,
                    relatedId: (_a = mark === null || mark === void 0 ? void 0 : mark.detail) === null || _a === void 0 ? void 0 : _a.relatedId,
                    level: performance_1.EPerformanceDebugLevel.Verbose
                });
            }
        });
    };
    SciChartRenderer.prototype.drawSvgAnnotations = function (svgAnnotations, coordSvgTranslation) {
        var _this = this;
        svgAnnotations.forEach(function (a) {
            var _a, _b, _c;
            a.linkAxes();
            var xAxis = a.xAxis;
            var yAxis = a.yAxis;
            if (!xAxis || !yAxis) {
                console.error("Cannot draw SVG annotations before axes have been configured. Add axes first, or use suspendUpdates to pause drawing until axes are available.");
                return;
            }
            if (xAxis.id !== a.xAxisId || yAxis.id !== a.yAxisId) {
                logger_1.Logger.log("SVG Annotation ".concat((_b = (_a = a.constructor) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : "", " has mismatched axis IDs. Expected xAxisId=").concat(a.xAxisId, ", yAxisId=").concat(a.yAxisId, " but got xAxis=").concat(xAxis.id, ", yAxis=").concat(yAxis.id));
            }
            var mark = performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.DrawAnnotationStart, {
                contextId: a.id,
                parentContextId: _this.sciChartSurface.id,
                level: performance_1.EPerformanceDebugLevel.Verbose
            });
            a.update(xAxis.getCurrentCoordinateCalculator(), yAxis.getCurrentCoordinateCalculator(), coordSvgTranslation.x / DpiHelper_1.DpiHelper.PIXEL_RATIO, coordSvgTranslation.y / DpiHelper_1.DpiHelper.PIXEL_RATIO);
            performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.DrawAnnotationEnd, {
                contextId: a.id,
                parentContextId: _this.sciChartSurface.id,
                relatedId: (_c = mark === null || mark === void 0 ? void 0 : mark.detail) === null || _c === void 0 ? void 0 : _c.relatedId,
                level: performance_1.EPerformanceDebugLevel.Verbose
            });
        });
    };
    SciChartRenderer.prototype.validate = function () {
        this.sciChartSurface.xAxes.asArray().forEach(function (axis) { return (axis.isMeasured = false); });
        this.sciChartSurface.yAxes.asArray().forEach(function (axis) { return (axis.isMeasured = false); });
        if (this.sciChartSurface.renderableSeries.size() > 0) {
            var errors = this.sciChartSurface.validateAndLink();
            if (errors.length > 0) {
                throw new Error(errors.join("\n"));
            }
        }
    };
    SciChartRenderer.prototype.resizeAnnotationRootElements = function (seriesViewRect) {
        // Convert seriesViewRect back to device pixels
        // e.g. at Retina display canvas size may be 400x300 but seriesViewRect size would be 800x600
        var clipRect = this.sciChartSurface.clipRect;
        var unscaledClipRect = (0, translate_1.translateToNotScaledRect)(clipRect);
        var seriesViewRectInDevicePixels = Rect_1.Rect.intersect((0, translate_1.translateToNotScaledRect)(seriesViewRect), unscaledClipRect);
        var surfaceViewRect = this.sciChartSurface.viewRect;
        var surfaceViewRectInDevicePixels = Rect_1.Rect.intersect((0, translate_1.translateToNotScaledRect)(surfaceViewRect), unscaledClipRect);
        if (!this.prevRect || !this.prevSurfaceRect) {
            this.prevRect = seriesViewRectInDevicePixels;
            this.prevSurfaceRect = surfaceViewRectInDevicePixels;
        }
        else if (Rect_1.Rect.isEqual(this.prevRect, seriesViewRectInDevicePixels) &&
            Rect_1.Rect.isEqual(this.prevSurfaceRect, surfaceViewRectInDevicePixels)) {
            return;
        }
        this.prevRect = seriesViewRectInDevicePixels;
        this.prevSurfaceRect = surfaceViewRect;
        var svgRootElement = this.sciChartSurface.domSvgContainer;
        if (svgRootElement) {
            this.sciChartSurface.setSvgClipPathDefinitions(svgRootElement, seriesViewRectInDevicePixels, surfaceViewRectInDevicePixels);
        }
        var backgroundSvgRootElement = this.sciChartSurface.domBackgroundSvgContainer;
        if (backgroundSvgRootElement) {
            this.sciChartSurface.setSvgClipPathDefinitions(backgroundSvgRootElement, seriesViewRectInDevicePixels, surfaceViewRectInDevicePixels);
        }
        var adornerRootElement = this.sciChartSurface.domSvgAdornerLayer;
        if (adornerRootElement) {
            this.sciChartSurface.setSvgClipPathDefinitions(adornerRootElement, seriesViewRectInDevicePixels, surfaceViewRectInDevicePixels);
        }
    };
    SciChartRenderer.prototype.prepareAxesRenderData = function () {
        // Prepare XAxes
        this.sciChartSurface.xAxes.asArray().forEach(function (xAxis) {
            xAxis.prepareRenderData();
        });
        // Prepare YAxes
        this.sciChartSurface.yAxes.asArray().forEach(function (yAxis) {
            yAxis.prepareRenderData();
        });
    };
    SciChartRenderer.prototype.prepareSeriesRenderData = function (seriesViewRect) {
        var _a, _b, _c;
        var seriesCount = this.sciChartSurface.renderableSeries.size();
        var renderPassInfo = new RenderPassInfo_1.RenderPassInfo(seriesCount, seriesViewRect);
        for (var i = 0; i < this.sciChartSurface.renderableSeries.size(); i++) {
            var series = this.sciChartSurface.renderableSeries.get(i);
            // don't try and draw series with no data
            if (!series.isCollection && !series.dataSeries)
                continue;
            // don't try and draw deleted dataseries
            if (!series.isCollection && series.dataSeries.getIsDeleted()) {
                throw new Error("SciChartSurface.renderableSeries[index=".concat(i, "] dataSeries has been deleted. ") +
                    "This is an invalid state for SciChart. Have you shared this DataSeries between chart surfaces?");
            }
            var resampleSingleSeriesStartMark = performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.ResampleSingleSeriesStart, {
                contextId: series.id,
                parentContextId: this.sciChartSurface.id,
                level: performance_1.EPerformanceDebugLevel.Verbose
            });
            var xAxis = series.xAxis;
            if (!xAxis.parentSurface) {
                console.error("Cannot draw series ".concat((_a = series === null || series === void 0 ? void 0 : series.constructor) === null || _a === void 0 ? void 0 : _a.name, " with X-axis detached from sciChartSurface. Set a correct xAxisId on the series"));
                continue;
            }
            var yAxis = series.yAxis;
            if (!yAxis.parentSurface) {
                console.error("Cannot draw series ".concat((_b = series === null || series === void 0 ? void 0 : series.constructor) === null || _b === void 0 ? void 0 : _b.name, " with Y-axis detached from sciChartSurface. Set a correct yAxisId on the series"));
                continue;
            }
            var seriesRenderPassInfo = ExtremeResamplerHelper_1.ExtremeResamplerHelper.resampleSeries(xAxis, series, seriesViewRect);
            renderPassInfo.renderableSeriesArray.push(seriesRenderPassInfo.renderableSeries);
            var renderPassData = new RenderPassData_1.RenderPassData(seriesRenderPassInfo.indicesRange, xAxis.getCurrentCoordinateCalculator, yAxis.getCurrentCoordinateCalculator, xAxis.isVerticalChart, seriesRenderPassInfo.pointSeries, seriesRenderPassInfo.resamplingHash);
            // Set the renderPassData early
            series.setCurrentRenderPassData(renderPassData);
            performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.ResampleSingleSeriesEnd, {
                contextId: series.id,
                parentContextId: this.sciChartSurface.id,
                relatedId: (_c = resampleSingleSeriesStartMark === null || resampleSingleSeriesStartMark === void 0 ? void 0 : resampleSingleSeriesStartMark.detail) === null || _c === void 0 ? void 0 : _c.relatedId,
                level: performance_1.EPerformanceDebugLevel.Verbose
            });
        }
        return renderPassInfo;
    };
    SciChartRenderer.prototype.drawAxes = function (scs, renderContext) {
        scs.xAxes.asArray().forEach(function (xAxis) {
            xAxis.draw(renderContext);
        });
        scs.yAxes.asArray().forEach(function (yAxis) {
            yAxis.draw(renderContext);
        });
    };
    SciChartRenderer.prototype.drawSeries = function (scs, renderPassInfo, renderContext) {
        var _this = this;
        var _a;
        var renderableSeriesArray = renderPassInfo.renderableSeriesArray;
        var viewRect = this.sciChartSurface.seriesViewRect;
        var clipRect = Rect_1.Rect.intersect(this.sciChartSurface.seriesViewRect, this.sciChartSurface.clipRect);
        renderContext.setTranslationRotationAndClip(clipRect, viewRect.x, viewRect.y);
        // Draw unselected series first
        renderableSeriesArray.forEach(function (rs, index) {
            if (rs.isVisible && !rs.isSelected && !rs.isHovered)
                rs.draw(renderContext, rs.getCurrentRenderPassData());
        });
        // Draw hovered series next
        renderableSeriesArray.forEach(function (rs, index) {
            if (rs.isVisible && rs.isHovered)
                rs.draw(renderContext, rs.getCurrentRenderPassData());
        });
        // Draw selected series at higher z-index
        renderableSeriesArray.forEach(function (rs, index) {
            if (rs.isVisible && rs.isSelected)
                rs.draw(renderContext, rs.getCurrentRenderPassData());
        });
        // Perform global text layout
        if (this.sciChartSurface.dataLabelLayoutManager) {
            var mark = performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.PerformTextLayoutStart, {
                contextId: this.sciChartSurface.id,
                level: performance_1.EPerformanceDebugLevel.Verbose
            });
            this.sciChartSurface.dataLabelLayoutManager.performTextLayout(this.sciChartSurface, renderPassInfo);
            performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.PerformTextLayoutEnd, {
                contextId: this.sciChartSurface.id,
                relatedId: (_a = mark === null || mark === void 0 ? void 0 : mark.detail) === null || _a === void 0 ? void 0 : _a.relatedId,
                level: performance_1.EPerformanceDebugLevel.Verbose
            });
        }
        // Draw series text
        renderableSeriesArray.forEach(function (rs, index) {
            var _a;
            if (rs.isVisible && rs.dataLabelProvider) {
                var mark = performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.DrawDataLabelsStart, {
                    contextId: rs.id,
                    parentContextId: _this.sciChartSurface.id,
                    level: performance_1.EPerformanceDebugLevel.Verbose
                });
                rs.dataLabelProvider.draw(renderContext);
                performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.DrawDataLabelsEnd, {
                    contextId: rs.id,
                    parentContextId: _this.sciChartSurface.id,
                    relatedId: (_a = mark === null || mark === void 0 ? void 0 : mark.detail) === null || _a === void 0 ? void 0 : _a.relatedId,
                    level: performance_1.EPerformanceDebugLevel.Verbose
                });
            }
        });
    };
    SciChartRenderer.prototype.drawDebugAxes = function (scs, renderContext) {
        renderContext.enqueueLayeredDraw(function () {
            scs.xAxes.asArray().forEach(function (xAxis) {
                xAxis.drawDebug(renderContext);
            });
            scs.yAxes.asArray().forEach(function (yAxis) {
                yAxis.drawDebug(renderContext);
            });
        });
    };
    SciChartRenderer.prototype.tryPerformAutoRangeOn = function (axis, sciChartSurface) {
        var firstRange = !axis.hasValidVisibleRange() || axis.hasDefaultVisibleRange();
        var shouldAutoRange = axis.autoRange === AutoRange_1.EAutoRange.Always || (axis.autoRange === AutoRange_1.EAutoRange.Once && firstRange);
        if (shouldAutoRange) {
            // Different implementation for YAxis and XAxis because of windowing
            var newRange = axis.getMaximumRange();
            if (!newRange.equals(axis.visibleRange)) {
                if (!axis.autoRangeAnimation ||
                    (firstRange && !axis.autoRangeAnimation.animateInitialRanging) ||
                    (!firstRange && !axis.autoRangeAnimation.animateSubsequentRanging)) {
                    axis.visibleRange = newRange;
                }
                else if (!newRange.equals(axis.animatedVisibleRange)) {
                    axis.animateVisibleRange(newRange, axis.autoRangeAnimation.duration, axis.autoRangeAnimation.easing);
                }
            }
        }
    };
    SciChartRenderer.prototype.onParentSurfaceRendered = function () {
        var _a;
        if (!this.sciChartSurface.isSubSurface) {
            this.sciChartSurface.chartModifiers.asArray().forEach(function (cm) {
                if (cm.modifierType !== ModifierType_1.EModifierType.Chart3DModifier) {
                    cm.linkAxes();
                }
                cm.onParentSurfaceRendered();
            });
        }
        // For subCharts, run this once from the parent surface, after draw has happened
        (_a = this.sciChartSurface.subCharts) === null || _a === void 0 ? void 0 : _a.forEach(function (sc) {
            if (sc.hasInvalidState)
                return;
            sc.chartModifiers.asArray().forEach(function (cm) {
                cm.onParentSurfaceRendered();
            });
        });
    };
    SciChartRenderer.prototype.updateWatermark = function (renderContext, seriesViewRect) {
        var chartHeight = this.sciChartSurface.isCopyCanvasSurface
            ? SciChartSurfaceBase_1.SciChartSurfaceBase.domMasterCanvas.height
            : renderContext.viewportSize.height;
        var chartWidth = this.sciChartSurface.isCopyCanvasSurface
            ? SciChartSurfaceBase_1.SciChartSurfaceBase.domMasterCanvas.width
            : renderContext.viewportSize.width;
        var _a = watermarkHelpers_1.watermarkHelpers.calcPosition(chartWidth, chartHeight, this.sciChartSurface.watermarkPosition, this.sciChartSurface.watermarkRelativeToCanvas, seriesViewRect, renderContext.viewportSize), left = _a.left, bottom = _a.bottom;
        this.sciChartSurface.updateWatermark(left, bottom);
    };
    SciChartRenderer.prototype.scheduleTitleDraw = function (renderContext) {
        var _this = this;
        renderContext.enqueueLayeredDraw(function () {
            _this.sciChartSurface.chartTitleRenderer.draw(renderContext, _this.sciChartSurface.clipRect);
        }, this.getAbsoluteLayer(DefaultRenderLayer_1.EDefaultRenderLayer.AnnotationsAboveSeriesLayer));
    };
    SciChartRenderer.prototype.measureTitle = function (renderContext) {
        this.sciChartSurface.chartTitleRenderer.measure(this.sciChartSurface.title, this.sciChartSurface.titleStyle, renderContext);
        return this.sciChartSurface.chartTitleRenderer.titleOffset;
    };
    SciChartRenderer.prototype.layoutTitle = function (seriesViewRect) {
        // current surface area which will contain title
        var chartViewRect = this.sciChartSurface.titleStyle.placeWithinChart
            ? seriesViewRect
            : this.sciChartSurface.viewRect;
        // title position calculation
        this.sciChartSurface.chartTitleRenderer.layout(chartViewRect);
    };
    SciChartRenderer.prototype.getAbsoluteLayer = function (relativeRenderLayer) {
        return (0, WebGlRenderContext2D_1.calculateAbsoluteRenderLayer)(this.sciChartSurface.getSurfaceRenderOrder(), this.sciChartSurface.stepBetweenLayers, relativeRenderLayer);
    };
    SciChartRenderer.prototype.drawDebugSurfaceRect = function (renderContext, viewRect, wasmContext) {
        var vecRects = (0, NativeObject_1.getVectorRectVertex)(wasmContext);
        var brush = new wasmContext.SCRTSolidBrush((0, parseColor_1.parseColorToUIntArgb)("rgba(0,255,0,0.7)"), false);
        var nativeRect = (0, createNativeRect_1.createNativeRect)(wasmContext, 0, 0, viewRect.width, viewRect.height);
        vecRects.push_back(nativeRect);
        renderContext.drawRects(vecRects, brush, this.sciChartSurface.chartViewRect, viewRect.left, viewRect.top);
        brush.delete();
    };
    return SciChartRenderer;
}());
exports.SciChartRenderer = SciChartRenderer;
