"use strict";
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.LineSegmentSeriesDrawingProvider = void 0;
var Deleter_1 = require("../../../../Core/Deleter");
var ValueName_1 = require("../../../../types/ValueName");
var Pen2DCache_1 = require("../../../Drawing/Pen2DCache");
var IDataSeries_1 = require("../../../Model/IDataSeries");
var constants_1 = require("../constants");
var BaseSeriesDrawingProvider_1 = require("./BaseSeriesDrawingProvider");
/**
 * Used internally - a drawing provider performs drawing for a {@link FastLineSegmentRenderableSeries} using
 * our WebAssembly WebGL rendering engine
 */
var LineSegmentSeriesDrawingProvider = /** @class */ (function (_super) {
    __extends(LineSegmentSeriesDrawingProvider, _super);
    /**
     * Creates an instance of the {@link LineSegmentSeriesDrawingProvider}
     * @param webAssemblyContext The {@link TSciChart | SciChart 2D WebAssembly Context} containing native methods and
     * access to our WebGL2 Engine and WebAssembly numerical methods
     * @param parentSeries the parent {@link FastLineSegmentRenderableSeries} which this drawing provider is attached to
     */
    function LineSegmentSeriesDrawingProvider(webAssemblyContext, parentSeries, ySelector, xSelector) {
        var _this = _super.call(this, webAssemblyContext, parentSeries, ySelector, xSelector) || this;
        _this.linesPenCache = new Pen2DCache_1.Pen2DCache(webAssemblyContext);
        _this.args = new webAssemblyContext.SCRTLineDrawingParams();
        return _this;
    }
    /** @inheritDoc */
    LineSegmentSeriesDrawingProvider.prototype.onDpiChanged = function (args) {
        _super.prototype.onDpiChanged.call(this, args);
        this.onSeriesPropertyChange(constants_1.PROPERTY.STROKE);
    };
    /** @inheritDoc */
    LineSegmentSeriesDrawingProvider.prototype.onSeriesPropertyChange = function (propertyName) {
        _super.prototype.onSeriesPropertyChange.call(this, propertyName);
        if (propertyName === constants_1.PROPERTY.PALETTE_PROVIDER) {
            this.linesPenCache.invalidateCache();
        }
        if (propertyName === constants_1.PROPERTY.STROKE ||
            propertyName === constants_1.PROPERTY.STROKE_THICKNESS ||
            propertyName === constants_1.PROPERTY.PALETTE_PROVIDER ||
            propertyName === constants_1.PROPERTY.OPACITY ||
            propertyName === constants_1.PROPERTY.STROKE_DASH_ARRAY) {
            this.palettingState.requiresUpdate = true;
            var _a = this.getProperties(this.parentSeries), stroke = _a.stroke, strokeThickness = _a.strokeThickness, opacity = _a.opacity, strokeDashArray = _a.strokeDashArray;
            if (stroke) {
                (0, Pen2DCache_1.createPenInCache)(this.linesPenCache, stroke, strokeThickness, opacity !== null && opacity !== void 0 ? opacity : 1, strokeDashArray, true);
            }
        }
    };
    /** A mapping function to get the pen properties from the parent series */
    LineSegmentSeriesDrawingProvider.prototype.getProperties = function (parentSeries) {
        var _a;
        var stroke = parentSeries.stroke, strokeThickness = parentSeries.strokeThickness, opacity = parentSeries.opacity, strokeDashArray = parentSeries.strokeDashArray, dataSeries = parentSeries.dataSeries;
        return {
            stroke: stroke,
            strokeThickness: strokeThickness,
            opacity: opacity,
            strokeDashArray: strokeDashArray,
            dataSeriesType: (_a = dataSeries === null || dataSeries === void 0 ? void 0 : dataSeries.type) !== null && _a !== void 0 ? _a : IDataSeries_1.EDataSeriesType.Xy
        };
    };
    /** @inheritDoc */
    LineSegmentSeriesDrawingProvider.prototype.onAttachSeries = function () {
        _super.prototype.onAttachSeries.call(this);
        this.nativeDrawingProvider = new this.webAssemblyContext.SCRTLineSegmentDrawingProvider();
        var _a = this.getProperties(this.parentSeries), stroke = _a.stroke, strokeThickness = _a.strokeThickness, opacity = _a.opacity, strokeDashArray = _a.strokeDashArray;
        if (stroke) {
            (0, Pen2DCache_1.createPenInCache)(this.linesPenCache, stroke, strokeThickness, opacity !== null && opacity !== void 0 ? opacity : 1, strokeDashArray, true);
        }
    };
    /** @inheritDoc */
    LineSegmentSeriesDrawingProvider.prototype.onDetachSeries = function () {
        _super.prototype.onDetachSeries.call(this);
        this.nativeDrawingProvider = (0, Deleter_1.deleteSafe)(this.nativeDrawingProvider);
    };
    /** @inheritDoc */
    LineSegmentSeriesDrawingProvider.prototype.getStartAndCount = function (renderPassData, xValues) {
        var _a, _b, _c;
        var pointSeries = renderPassData === null || renderPassData === void 0 ? void 0 : renderPassData.pointSeries;
        var xAxis = (_a = this.parentSeries) === null || _a === void 0 ? void 0 : _a.xAxis;
        var shouldClip = (_b = xAxis === null || xAxis === void 0 ? void 0 : xAxis.clipToXRange) !== null && _b !== void 0 ? _b : true; // for the sake of tests
        var xCount = xValues.size();
        var count = Math.min(pointSeries ? pointSeries.xValues.size() : xCount, xCount);
        var startIndex = 0;
        if (shouldClip && !(pointSeries === null || pointSeries === void 0 ? void 0 : pointSeries.resampled) && ((_c = renderPassData === null || renderPassData === void 0 ? void 0 : renderPassData.indexRange) === null || _c === void 0 ? void 0 : _c.diff) >= 0) {
            if (renderPassData.indexRange.diff + 1 < count) {
                startIndex = renderPassData.indexRange.min;
            }
            count = Math.min(renderPassData.indexRange.diff + 1, count);
            if (startIndex % 2 === 1) {
                startIndex--;
                count++;
            }
        }
        return { startIndex: startIndex, count: count };
    };
    /** A hook so derived classes can change the args */
    LineSegmentSeriesDrawingProvider.prototype.updateArgs = function (renderPassData) { };
    /**
     * Drawing two vectors xValues: [x1_1, x1_2, x2_1, x2_2,...], yValues: [y1_1, y1_2, y2_1, y2_2,...]
     */
    LineSegmentSeriesDrawingProvider.prototype.drawXy = function (renderContext, renderPassData) {
        var stroke = this.getProperties(this.parentSeries).stroke;
        var linesPen = (0, Pen2DCache_1.getScrtPenFromCache)(this.linesPenCache);
        if (!linesPen || !stroke)
            return;
        this.args.Reset();
        this.args.SetLinesPen(linesPen);
        this.args.forceShaderMethod = true;
        this.args.forceClamp = true;
        this.args.verticalChart = renderPassData.isVerticalChart;
        var isCategoryAxis = renderPassData.xCoordinateCalculator.isCategoryCoordinateCalculator;
        if (isCategoryAxis) {
            console.error("Category Axis is not supported for LineSegmentRenderableSeries");
            return;
        }
        var pointSeries = renderPassData.pointSeries;
        var xDrawValues = this.xSelector(pointSeries);
        var yDrawValues = this.ySelector(pointSeries);
        var _a = this.getStartAndCount(renderPassData, xDrawValues), startIndex = _a.startIndex, count = _a.count;
        this.args.count = count;
        this.args.startIndex = startIndex;
        // Stroke paletting per point
        this.applyStrokePaletting(linesPen, renderPassData);
        if (this.palettingState.palettedColors) {
            this.args.SetPalettedColors(this.palettingState.palettedColors);
        }
        this.updateArgs(renderPassData);
        var nativeContext = renderContext.getNativeContext();
        this.drawLines(renderContext, nativeContext, xDrawValues, yDrawValues, renderPassData.xCoordinateCalculator.nativeCalculator, renderPassData.yCoordinateCalculator.nativeCalculator, this.args, this.parentSeries.parentSurface.seriesViewRect);
    };
    /**
     * Drawing two vectors xValues: [x1_1, x2_1,...], yValues: [y1_1, y2_1,...],  x1Values: [x1_2, x2_2,...], y1Values: [y1_2, y2_2,...]
     */
    LineSegmentSeriesDrawingProvider.prototype.drawXyXy = function (renderContext, renderPassData) {
        var stroke = this.getProperties(this.parentSeries).stroke;
        var linesPen = (0, Pen2DCache_1.getScrtPenFromCache)(this.linesPenCache);
        if (!linesPen || !stroke)
            return;
        this.args.Reset();
        this.args.fourVectorsMode = true; // setting 4 vectors mode
        this.args.SetLinesPen(linesPen);
        this.args.forceShaderMethod = true;
        // this.args.forceClamp = true;
        this.args.verticalChart = renderPassData.isVerticalChart;
        var isCategoryAxis = renderPassData.xCoordinateCalculator.isCategoryCoordinateCalculator;
        if (isCategoryAxis) {
            console.error("Category Axis is not supported for LineSegmentRenderableSeries");
            return;
        }
        var pointSeries = renderPassData.pointSeries;
        var xDrawValues = this.xSelector(pointSeries);
        var yDrawValues = this.ySelector(pointSeries);
        var x1DrawValues = pointSeries.getYValuesByName(ValueName_1.EValueName.X1);
        var y1DrawValues = pointSeries.getYValuesByName(ValueName_1.EValueName.Y1);
        var _a = this.getStartAndCount(renderPassData, xDrawValues), startIndex = _a.startIndex, count = _a.count;
        this.args.count = count;
        this.args.startIndex = startIndex;
        this.args.SetZValues(x1DrawValues);
        this.args.SetWValues(y1DrawValues);
        // For 4 vectors we can not do gradients, because we consider each line segment to be single entity
        this.applyStrokePaletting(linesPen, renderPassData);
        if (this.palettingState.palettedColors) {
            this.args.SetPalettedColors(this.palettingState.palettedColors);
            this.args.SetPalettedColors2(this.palettingState.palettedColors);
        }
        this.updateArgs(renderPassData);
        var nativeContext = renderContext.getNativeContext();
        this.drawLines(renderContext, nativeContext, xDrawValues, yDrawValues, renderPassData.xCoordinateCalculator.nativeCalculator, renderPassData.yCoordinateCalculator.nativeCalculator, this.args, this.parentSeries.parentSurface.seriesViewRect);
    };
    /** @inheritDoc */
    LineSegmentSeriesDrawingProvider.prototype.draw = function (renderContext, renderPassData) {
        var dataSeriesType = this.getProperties(this.parentSeries).dataSeriesType;
        if (dataSeriesType === IDataSeries_1.EDataSeriesType.Xyxy) {
            this.drawXyXy(renderContext, renderPassData);
        }
        else {
            this.drawXy(renderContext, renderPassData);
        }
    };
    /**
     * @inheritDoc
     */
    LineSegmentSeriesDrawingProvider.prototype.delete = function () {
        this.linesPenCache = (0, Deleter_1.deleteSafe)(this.linesPenCache);
        this.nativeDrawingProvider = (0, Deleter_1.deleteSafe)(this.nativeDrawingProvider);
        this.args = (0, Deleter_1.deleteSafe)(this.args);
        _super.prototype.delete.call(this);
    };
    LineSegmentSeriesDrawingProvider.prototype.drawLines = function (renderContext, nativeContext, xValues, yValues, xCoordCalc, yCoordCalc, args, viewRect) {
        if (args.count <= 0)
            return;
        args.SetNativeContext(nativeContext);
        args.SetXValues(xValues);
        args.SetYValues(yValues);
        args.SetXCoordinateCalculator(xCoordCalc);
        args.SetYCoordinateCalculator(yCoordCalc);
        this.nativeDrawingProvider.DrawLinesVec(args);
    };
    return LineSegmentSeriesDrawingProvider;
}(BaseSeriesDrawingProvider_1.BaseSeriesDrawingProvider));
exports.LineSegmentSeriesDrawingProvider = LineSegmentSeriesDrawingProvider;
