"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.sciChartSubSurfaceCommon = void 0;
var performanceWarnings_1 = require("../../constants/performanceWarnings");
var Deleter_1 = require("../../Core/Deleter");
var Rect_1 = require("../../Core/Rect");
var Thickness_1 = require("../../Core/Thickness");
var SubSurfacePosition_1 = require("../../types/SubSurfacePosition");
var SubSurfacePositionCoordinateMode_1 = require("../../types/SubSurfacePositionCoordinateMode");
var object_1 = require("../../utils/object");
var parseColor_1 = require("../../utils/parseColor");
var translate_1 = require("../../utils/translate");
var BrushCache_1 = require("../Drawing/BrushCache");
var createNativeRect_1 = require("./Helpers/createNativeRect");
var NativeObject_1 = require("./Helpers/NativeObject");
function createSubSurfaceCanvases(parentSurface) {
    // TODO check if it's enough for subcharts to reuse main surface canvases
    // const divElementId = parentSurface.domChartRoot.id + "_" + parentSurface.subChartCounter.toString();
    // const chartRoot = parentSurface.domChartRoot;
    // const width = chartRoot.clientWidth;
    // const height = chartRoot.clientHeight;
    // // SVG Root Element
    // const svgRootElement = createSvgLayer(`${divElementId}_SVG`, width, height);
    // svgRootElement.style.left = "0";
    // svgRootElement.style.top = "0";
    // svgRootElement.style.pointerEvents = "none";
    // svgRootElement.classList.add(ELayerClass.FRONT_SVG_ROOT);
    // chartRoot.insertBefore(svgRootElement, parentSurface.domSvgAdornerLayer);
    // // SVG Root Element
    // const backgroundSvgRootElement = createSvgLayer(`${divElementId}_BACKGROUND_SVG`, width, height);
    // backgroundSvgRootElement.style.left = "0";
    // backgroundSvgRootElement.style.top = "0";
    // backgroundSvgRootElement.style.pointerEvents = "none";
    // backgroundSvgRootElement.classList.add(ELayerClass.BACK_SVG_ROOT);
    // chartRoot.insertBefore(backgroundSvgRootElement, parentSurface.getMainCanvas());
    // // Background Div Root Element
    // const backgroundDomRoot = document.createElement("div");
    // backgroundDomRoot.id = `${divElementId}_background_div`;
    // backgroundDomRoot.classList.add(ELayerClass.DIV_ROOT, ELayerClass.BACK_DIV_ROOT);
    // backgroundDomRoot.style.left = "0";
    // backgroundDomRoot.style.top = "0";
    // backgroundDomRoot.style.position = "absolute";
    // backgroundDomRoot.style.pointerEvents = "none";
    // chartRoot.insertBefore(backgroundDomRoot, backgroundSvgRootElement);
    var canvases = {
        domChartRoot: parentSurface.domChartRoot,
        domCanvasWebGL: parentSurface.domCanvasWebGL,
        domCanvas2D: parentSurface.domCanvas2D,
        domSvgContainer: parentSurface.domSvgContainer,
        domSvgAdornerLayer: parentSurface.domSvgAdornerLayer,
        domDivContainer: parentSurface.domDivContainer,
        domBackgroundSvgContainer: parentSurface.domBackgroundSvgContainer,
        domSeriesBackground: parentSurface.domSeriesBackground
    };
    return canvases;
}
function getSubChartRect(sub) {
    var _a = sub.renderSurface.viewportSize, width = _a.width, height = _a.height;
    var _b = sub.offset, top = _b.top, left = _b.left, bottom = _b.bottom, right = _b.right;
    // When resizing too fast it could happen that width < left + right or height < top + bottom and it breaks subcharts
    var newWidth = width - left - right > 0 ? width - left - right : 0;
    var newHeight = height - top - bottom > 0 ? height - top - bottom : 0;
    return new Rect_1.Rect(left, top, newWidth, newHeight);
}
function deleteSubChart(sub, clearHtml) {
    // Now, no separate canvases are created for subcharts, so no need to clean them here
    // // Don't ever clear html on the parent here as it kills the drawing for all subcharts.
    // if (clearHtml && sub.domChartRoot.contains(sub.domSvgContainer)) {
    //     sub.domChartRoot.removeChild(sub.domSvgContainer);
    // }
    // if (clearHtml && sub.domChartRoot.contains(sub.domBackgroundSvgContainer)) {
    //     sub.domChartRoot.removeChild(sub.domBackgroundSvgContainer);
    // }
    sub.backgroundFillBrushCache = (0, Deleter_1.deleteSafe)(sub.backgroundFillBrushCache);
}
function parseCoordinateMode(coordinateMode) {
    var isArrayFormat = Array.isArray(coordinateMode);
    if (!isArrayFormat) {
        // the same mode for all coordinates
        return [coordinateMode, coordinateMode, coordinateMode, coordinateMode];
    }
    else if (coordinateMode.length === 1) {
        // also the same mode for all coordinates
        return [coordinateMode[0], coordinateMode[0], coordinateMode[0], coordinateMode[0]];
    }
    else if (coordinateMode.length === 2) {
        // separate modes for horizontal and vertical dimensions
        return [coordinateMode[0], coordinateMode[1], coordinateMode[0], coordinateMode[1]];
    }
    else if (coordinateMode.length === 4) {
        // each coordinate with a separate mode
        return coordinateMode;
    }
    else {
        throw new Error("Invalid subChart coordinate mode provided: ".concat(coordinateMode));
    }
}
function calcPadding(sub) {
    var _a = sub.parentSurface.viewRect, viewWidth = _a.width, viewHeight = _a.height;
    var parsedCoordinateModes = parseCoordinateMode(sub.coordinateMode);
    // defines whether any position coordinate value is bound to DataValue coordinate space
    var isBoundToDataValue = sub.coordinateMode === SubSurfacePositionCoordinateMode_1.ESubSurfacePositionCoordinateMode.DataValue ||
        sub.coordinateMode.includes(SubSurfacePositionCoordinateMode_1.ESubSurfacePositionCoordinateMode.DataValue);
    var position = sub.subPosition;
    var isXywhCoordinatesFormat = (0, object_1.hasProperties)(position, SubSurfacePosition_1.xywhFormatRequiredFieldNames);
    var isLtrbCoordinatesFormat = (0, object_1.hasProperties)(position, SubSurfacePosition_1.ltrbFormatRequiredFieldNames);
    var isPolygonCoordinatesFormat = (0, object_1.hasProperties)(position, SubSurfacePosition_1.polygonFormatRequiredFieldNames);
    // offsets of the reference axes
    var _b = sub.parentSurface.seriesViewRect, leftPadding = _b.left, topPadding = _b.top;
    var _c = getReferenceCoordCalcsForSubSurface(sub), horizontalCalc = _c.horizontalCalc, verticalCalc = _c.verticalCalc, xFlipped = _c.xFlipped, yFlipped = _c.yFlipped;
    if (isXywhCoordinatesFormat && isBoundToDataValue) {
        var xMode = parsedCoordinateModes[0], yMode = parsedCoordinateModes[1], widthMode = parsedCoordinateModes[2], heightMode = parsedCoordinateModes[3];
        var x = position.x, y = position.y, width = position.width, height = position.height;
        var leftAbsolute = translateToAbsoluteCoordinate(x, xMode, viewWidth, horizontalCalc, leftPadding);
        var topAbsolute = translateToAbsoluteCoordinate(y, yMode, viewHeight, verticalCalc, topPadding);
        // handle case when x and width have different coordinate modes
        var leftCoordInSameAsWidthMode = translateFromAbsoluteCoordinate(leftAbsolute, widthMode, viewWidth, horizontalCalc, leftPadding);
        var right = xFlipped ? leftCoordInSameAsWidthMode - width : leftCoordInSameAsWidthMode + width;
        var rightAbsolute = translateToAbsoluteCoordinate(right, widthMode, viewWidth, horizontalCalc, leftPadding);
        // handle case when y and height have different coordinate modes
        var topCoordInSameAsHeightMode = translateFromAbsoluteCoordinate(topAbsolute, heightMode, viewHeight, verticalCalc, topPadding);
        var bottom = yFlipped ? topCoordInSameAsHeightMode + height : topCoordInSameAsHeightMode - height;
        var bottomAbsolute = translateToAbsoluteCoordinate(bottom, heightMode, viewHeight, verticalCalc, topPadding);
        return new Thickness_1.Thickness(topAbsolute, viewWidth - rightAbsolute, viewHeight - bottomAbsolute, leftAbsolute);
    }
    else if (isXywhCoordinatesFormat && !isBoundToDataValue) {
        var xMode = parsedCoordinateModes[0], yMode = parsedCoordinateModes[1], widthMode = parsedCoordinateModes[2], heightMode = parsedCoordinateModes[3];
        var x = position.x, y = position.y, width = position.width, height = position.height;
        var leftAbsolute = translateToAbsoluteCoordinate(x, xMode, viewWidth);
        var topAbsolute = translateToAbsoluteCoordinate(y, yMode, viewHeight);
        var widthAbsolute = translateToAbsoluteCoordinate(width, widthMode, viewWidth);
        var heightAbsolute = translateToAbsoluteCoordinate(height, heightMode, viewHeight);
        var rightAbsolute = leftAbsolute + widthAbsolute;
        var borromAbsolute = topAbsolute + heightAbsolute;
        return new Thickness_1.Thickness(topAbsolute, viewWidth - rightAbsolute, viewHeight - borromAbsolute, leftAbsolute);
    }
    else if (isLtrbCoordinatesFormat) {
        var leftMode = parsedCoordinateModes[0], topMode = parsedCoordinateModes[1], rightMode = parsedCoordinateModes[2], bottomMode = parsedCoordinateModes[3];
        var left = position.left, top_1 = position.top, right = position.right, bottom = position.bottom;
        var leftAbsolute = translateToAbsoluteCoordinate(left, leftMode, viewWidth, horizontalCalc, leftPadding);
        var topAbsolute = translateToAbsoluteCoordinate(top_1, topMode, viewHeight, verticalCalc, topPadding);
        var rightAbsolute = translateToAbsoluteCoordinate(right, rightMode, viewWidth, horizontalCalc, leftPadding);
        var bottomAbsolute = translateToAbsoluteCoordinate(bottom, bottomMode, viewHeight, verticalCalc, topPadding);
        return new Thickness_1.Thickness(topAbsolute, viewWidth - rightAbsolute, viewHeight - bottomAbsolute, leftAbsolute);
    }
    else if (isPolygonCoordinatesFormat) {
        var x1Mode = parsedCoordinateModes[0], y1Mode = parsedCoordinateModes[1], x2Mode = parsedCoordinateModes[2], y2Mode = parsedCoordinateModes[3];
        var x1 = position.x1, y1 = position.y1, x2 = position.x2, y2 = position.y2;
        var x1Absolute = translateToAbsoluteCoordinate(x1, x1Mode, viewWidth, horizontalCalc, leftPadding);
        var y1Absolute = translateToAbsoluteCoordinate(y1, y1Mode, viewHeight, verticalCalc, topPadding);
        var x2Absolute = translateToAbsoluteCoordinate(x2, x2Mode, viewWidth, horizontalCalc, leftPadding);
        var y2Absolute = translateToAbsoluteCoordinate(y2, y2Mode, viewHeight, verticalCalc, topPadding);
        // swap sides if needed
        var leftAbsolute = Math.min(x1Absolute, x2Absolute);
        var topAbsolute = Math.min(y1Absolute, y2Absolute);
        var rightAbsolute = Math.max(x1Absolute, x2Absolute);
        var bottomAbsolute = Math.max(y1Absolute, y2Absolute);
        return new Thickness_1.Thickness(topAbsolute, viewWidth - rightAbsolute, viewHeight - bottomAbsolute, leftAbsolute);
    }
    throw new Error("Unexpected position format or coordinate mode ".concat(sub.coordinateMode, "!"));
}
function applySciChartBackground(sub, background, renderContext) {
    if (!sub.isTransparent && sub.isSubSurface) {
        var nativeContext = renderContext.getNativeContext();
        var viewRect = sub.viewRect;
        var clipRect = Rect_1.Rect.intersect(viewRect, sub.clipRect);
        renderContext.setTranslationRotationAndClip(clipRect, viewRect.x, viewRect.y);
        nativeContext.SetClearColor(0, 0, 0, 0);
        nativeContext.Clear();
        try {
            // try parse background value. throws if cannot parse html color
            var brushColor = (0, parseColor_1.parseColorToUIntArgb)(background);
            var vecRects = (0, NativeObject_1.getVectorRectVertex)(sub.webAssemblyContext2D);
            vecRects.push_back((0, createNativeRect_1.createNativeRect)(sub.webAssemblyContext2D, viewRect.left, viewRect.top, viewRect.right, viewRect.bottom));
            var brush = (0, BrushCache_1.createBrushInCache)(sub.backgroundFillBrushCache, background, 1);
            renderContext.drawRects(vecRects, brush, clipRect, 0, 0);
        }
        catch (error) {
            performanceWarnings_1.performanceWarnings.subchartBackgroundNotSimpleColor.warn();
        }
    }
}
function updateWrapper(sub, padding) {
    if (!sub.parentSurface || !sub.subChartContainer) {
        return;
    }
    var _a = (0, translate_1.translateToNotScaledRect)(sub.parentSurface.viewRect), viewWidth = _a.width, viewHeight = _a.height;
    sub.subChartContainer.style.left = (0, translate_1.convertToHtmlPx)(padding.left);
    sub.subChartContainer.style.top = (0, translate_1.convertToHtmlPx)(padding.top);
    sub.subChartContainer.style.width = (0, translate_1.convertToHtmlPx)(viewWidth - padding.left - padding.right);
    sub.subChartContainer.style.height = (0, translate_1.convertToHtmlPx)(viewHeight - padding.top - padding.bottom);
}
function getOffsets(sub, subChartContainer) {
    var _a, _b, _c, _d;
    if (!subChartContainer) {
        return Thickness_1.Thickness.fromNumber(0);
    }
    // TODO probably we can use better selector
    var leftSection = subChartContainer.getElementsByClassName(sub.leftSectionClass)[0];
    var topSection = subChartContainer.getElementsByClassName(sub.topSectionClass)[0];
    var rightSection = subChartContainer.getElementsByClassName(sub.rightSectionClass)[0];
    var bottomSection = subChartContainer.getElementsByClassName(sub.bottomSectionClass)[0];
    var leftSectionWidth = (_a = leftSection === null || leftSection === void 0 ? void 0 : leftSection.clientWidth) !== null && _a !== void 0 ? _a : 0;
    var topSectionHeight = (_b = topSection === null || topSection === void 0 ? void 0 : topSection.clientHeight) !== null && _b !== void 0 ? _b : 0;
    var rightSectionWidth = (_c = rightSection === null || rightSection === void 0 ? void 0 : rightSection.clientWidth) !== null && _c !== void 0 ? _c : 0;
    var bottomSectionHeight = (_d = bottomSection === null || bottomSection === void 0 ? void 0 : bottomSection.clientHeight) !== null && _d !== void 0 ? _d : 0;
    return new Thickness_1.Thickness((0, translate_1.translateToScaled)(topSectionHeight * sub.sectionScale), (0, translate_1.translateToScaled)(rightSectionWidth * sub.sectionScale), (0, translate_1.translateToScaled)(bottomSectionHeight * sub.sectionScale), (0, translate_1.translateToScaled)(leftSectionWidth * sub.sectionScale));
}
exports.sciChartSubSurfaceCommon = {
    createSubSurfaceCanvases: createSubSurfaceCanvases,
    getSubChartRect: getSubChartRect,
    deleteSubChart: deleteSubChart,
    calcPadding: calcPadding,
    applySciChartBackground: applySciChartBackground,
    updateWrapper: updateWrapper,
    getOffsets: getOffsets
};
var getReferenceCoordCalcsForSubSurface = function (subSurface) {
    var _a, _b;
    var isBoundToDataValue = subSurface.coordinateMode === SubSurfacePositionCoordinateMode_1.ESubSurfacePositionCoordinateMode.DataValue ||
        subSurface.coordinateMode.includes(SubSurfacePositionCoordinateMode_1.ESubSurfacePositionCoordinateMode.DataValue);
    if (!isBoundToDataValue) {
        return {};
    }
    var xAxis = (_a = subSurface.parentSurface.getXAxisById(subSurface.parentXAxisId)) !== null && _a !== void 0 ? _a : subSurface.parentSurface.getDefaultXAxis();
    if (!xAxis) {
        throw new Error("No x axis with id ".concat(subSurface.parentXAxisId, " found on parent surface"));
    }
    var xCoordCalc = xAxis.getCurrentCoordinateCalculator();
    var yAxis = (_b = subSurface.parentSurface.getYAxisById(subSurface.parentYAxisId)) !== null && _b !== void 0 ? _b : subSurface.parentSurface.getDefaultYAxis();
    if (!yAxis) {
        throw new Error("No y axis with id ".concat(subSurface.parentYAxisId, " found on parent surface"));
    }
    var yCoordCalc = yAxis.getCurrentCoordinateCalculator();
    var horizontalCalc = xAxis.isVerticalChart ? yCoordCalc : xCoordCalc;
    var verticalCalc = xAxis.isVerticalChart ? xCoordCalc : yCoordCalc;
    var xFlipped = xAxis.flippedCoordinates;
    var yFlipped = yAxis.flippedCoordinates;
    return { horizontalCalc: horizontalCalc, verticalCalc: verticalCalc, xFlipped: xFlipped, yFlipped: yFlipped };
};
function translateToAbsoluteCoordinate(value, coordinateMode, referenceSize, coordinateCalculator, axisOffset) {
    switch (coordinateMode) {
        case SubSurfacePositionCoordinateMode_1.ESubSurfacePositionCoordinateMode.Pixel: {
            return (0, translate_1.translateToScaled)(value);
        }
        case SubSurfacePositionCoordinateMode_1.ESubSurfacePositionCoordinateMode.Relative: {
            return referenceSize * value;
        }
        case SubSurfacePositionCoordinateMode_1.ESubSurfacePositionCoordinateMode.DataValue: {
            return axisOffset + coordinateCalculator.getCoordinate(value);
        }
    }
}
function translateFromAbsoluteCoordinate(value, coordinateMode, referenceSize, coordinateCalculator, calcPadding) {
    switch (coordinateMode) {
        case SubSurfacePositionCoordinateMode_1.ESubSurfacePositionCoordinateMode.Pixel: {
            return (0, translate_1.translateToNotScaled)(value);
        }
        case SubSurfacePositionCoordinateMode_1.ESubSurfacePositionCoordinateMode.Relative: {
            return value / referenceSize;
        }
        case SubSurfacePositionCoordinateMode_1.ESubSurfacePositionCoordinateMode.DataValue: {
            return coordinateCalculator.getDataValue(value - calcPadding);
        }
    }
}
