"use strict";
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.renderBarValues = void 0;
var color_calcs_1 = require("../../../../../common/color_calcs");
var fill_text_color_1 = require("../../../../../common/fill_text_color");
var common_1 = require("../../../../../utils/common");
var text_1 = require("../primitives/text");
var debug_1 = require("../utils/debug");
var panel_transform_1 = require("../utils/panel_transform");
var CHART_DIRECTION = {
    BottomUp: 0,
    TopToBottom: 180,
    LeftToRight: 90,
    RightToLeft: -90,
};
function renderBarValues(ctx, props) {
    var bars = props.bars, debug = props.debug, rotation = props.rotation, renderingArea = props.renderingArea, barSeriesStyle = props.barSeriesStyle, panel = props.panel;
    var _a = barSeriesStyle.displayValue, fontFamily = _a.fontFamily, fontStyle = _a.fontStyle, fill = _a.fill, alignment = _a.alignment;
    var barsLength = bars.length;
    var _loop_1 = function (i) {
        var displayValue = bars[i].displayValue;
        if (!displayValue) {
            return "continue";
        }
        var text = displayValue.text, fontSize = displayValue.fontSize, fontScale = displayValue.fontScale;
        var textLines = {
            lines: [text],
            width: displayValue.width,
            height: displayValue.height,
        };
        var font = {
            fontFamily: fontFamily,
            fontStyle: fontStyle ? fontStyle : 'normal',
            fontVariant: 'normal',
            fontWeight: 'normal',
            textColor: 'black',
            textOpacity: 1,
        };
        var _a = positionText(bars[i], displayValue, rotation, barSeriesStyle.displayValue, alignment), x = _a.x, y = _a.y, align = _a.align, baseline = _a.baseline, rect = _a.rect;
        if (displayValue.isValueContainedInElement) {
            var width_1 = rotation === 0 || rotation === 180 ? bars[i].width : bars[i].height;
            textLines = text_1.wrapLines(ctx, textLines.lines[0], font, fontSize, width_1, 100);
        }
        if (displayValue.hideClippedValue && isOverflow(rect, renderingArea, rotation)) {
            return "continue";
        }
        if (debug) {
            debug_1.renderDebugRect(ctx, rect);
        }
        var width = textLines.width, height = textLines.height;
        var linesLength = textLines.lines.length;
        var shadowSize = getTextBorderSize(fill);
        var _b = getTextColors(fill, bars[i].color, shadowSize), fillColor = _b.fillColor, shadowColor = _b.shadowColor;
        var _loop_2 = function (j) {
            var textLine = textLines.lines[j];
            var origin_1 = repositionTextLine({ x: x, y: y }, rotation, j, linesLength, { height: height, width: width });
            panel_transform_1.withPanelTransform(ctx, panel, rotation, renderingArea, function (ctx) {
                text_1.renderText(ctx, origin_1, textLine, __assign(__assign({}, font), { fill: fillColor, fontSize: fontSize,
                    align: align,
                    baseline: baseline, shadow: shadowColor, shadowSize: shadowSize }), -rotation, undefined, fontScale);
            });
        };
        for (var j = 0; j < linesLength; j++) {
            _loop_2(j);
        }
    };
    for (var i = 0; i < barsLength; i++) {
        _loop_1(i);
    }
}
exports.renderBarValues = renderBarValues;
function repositionTextLine(origin, chartRotation, i, max, box) {
    var x = origin.x, y = origin.y;
    var width = box.width, height = box.height;
    var lineX;
    var lineY;
    switch (chartRotation) {
        case 180:
            lineX = x;
            lineY = y - (i - max + 1) * height;
            break;
        case -90:
            lineX = x;
            lineY = y;
            break;
        case 90:
            lineX = x;
            lineY = y - (i - max + 1) * width;
            break;
        case 0:
        default:
            lineX = x;
            lineY = y + i * height;
    }
    return { x: lineX, y: lineY };
}
function computeHorizontalOffset(geom, valueBox, chartRotation, _a) {
    var _b = _a === void 0 ? {} : _a, horizontal = _b.horizontal;
    switch (chartRotation) {
        case CHART_DIRECTION.LeftToRight: {
            if (horizontal === common_1.HorizontalAlignment.Left) {
                return geom.height - valueBox.width;
            }
            if (horizontal === common_1.HorizontalAlignment.Center) {
                return geom.height / 2 - valueBox.width / 2;
            }
            break;
        }
        case CHART_DIRECTION.RightToLeft: {
            if (horizontal === common_1.HorizontalAlignment.Right) {
                return geom.height - valueBox.width;
            }
            if (horizontal === common_1.HorizontalAlignment.Center) {
                return geom.height / 2 - valueBox.width / 2;
            }
            break;
        }
        case CHART_DIRECTION.TopToBottom: {
            if (horizontal === common_1.HorizontalAlignment.Left) {
                return geom.width / 2 - valueBox.width / 2;
            }
            if (horizontal === common_1.HorizontalAlignment.Right) {
                return -geom.width / 2 + valueBox.width / 2;
            }
            break;
        }
        case CHART_DIRECTION.BottomUp:
        default: {
            if (horizontal === common_1.HorizontalAlignment.Left) {
                return -geom.width / 2 + valueBox.width / 2;
            }
            if (horizontal === common_1.HorizontalAlignment.Right) {
                return geom.width / 2 - valueBox.width / 2;
            }
        }
    }
    return 0;
}
function computeVerticalOffset(geom, valueBox, chartRotation, _a) {
    var _b = _a === void 0 ? {} : _a, vertical = _b.vertical;
    switch (chartRotation) {
        case CHART_DIRECTION.LeftToRight: {
            if (vertical === common_1.VerticalAlignment.Bottom) {
                return geom.width - valueBox.height;
            }
            if (vertical === common_1.VerticalAlignment.Middle) {
                return geom.width / 2 - valueBox.height / 2;
            }
            break;
        }
        case CHART_DIRECTION.RightToLeft: {
            if (vertical === common_1.VerticalAlignment.Bottom) {
                return -geom.width + valueBox.height;
            }
            if (vertical === common_1.VerticalAlignment.Middle) {
                return -geom.width / 2 + valueBox.height / 2;
            }
            break;
        }
        case CHART_DIRECTION.TopToBottom: {
            if (vertical === common_1.VerticalAlignment.Top) {
                return geom.height - valueBox.height;
            }
            if (vertical === common_1.VerticalAlignment.Middle) {
                return geom.height / 2 - valueBox.height / 2;
            }
            break;
        }
        case CHART_DIRECTION.BottomUp:
        default: {
            if (vertical === common_1.VerticalAlignment.Bottom) {
                return geom.height - valueBox.height;
            }
            if (vertical === common_1.VerticalAlignment.Middle) {
                return geom.height / 2 - valueBox.height / 2;
            }
        }
    }
    return 0;
}
function computeAlignmentOffset(geom, valueBox, chartRotation, textAlignment) {
    if (textAlignment === void 0) { textAlignment = {}; }
    return {
        alignmentOffsetX: computeHorizontalOffset(geom, valueBox, chartRotation, textAlignment),
        alignmentOffsetY: computeVerticalOffset(geom, valueBox, chartRotation, textAlignment),
    };
}
function positionText(geom, valueBox, chartRotation, offsets, alignment) {
    var offsetX = offsets.offsetX, offsetY = offsets.offsetY;
    var _a = computeAlignmentOffset(geom, valueBox, chartRotation, alignment), alignmentOffsetX = _a.alignmentOffsetX, alignmentOffsetY = _a.alignmentOffsetY;
    switch (chartRotation) {
        case CHART_DIRECTION.TopToBottom: {
            var x = geom.x + geom.width / 2 - offsetX + alignmentOffsetX;
            var y = geom.y + offsetY + alignmentOffsetY;
            return {
                x: x,
                y: y,
                align: 'center',
                baseline: 'bottom',
                rect: {
                    x: x - valueBox.width / 2,
                    y: y,
                    width: valueBox.width,
                    height: valueBox.height,
                },
            };
        }
        case CHART_DIRECTION.RightToLeft: {
            var x = geom.x + geom.width + offsetY + alignmentOffsetY;
            var y = geom.y - offsetX + alignmentOffsetX;
            return {
                x: x,
                y: y,
                align: 'left',
                baseline: 'top',
                rect: {
                    x: x - valueBox.height,
                    y: y,
                    width: valueBox.height,
                    height: valueBox.width,
                },
            };
        }
        case CHART_DIRECTION.LeftToRight: {
            var x = geom.x - offsetY + alignmentOffsetY;
            var y = geom.y + offsetX + alignmentOffsetX;
            return {
                x: x,
                y: y,
                align: 'right',
                baseline: 'top',
                rect: {
                    x: x,
                    y: y,
                    width: valueBox.height,
                    height: valueBox.width,
                },
            };
        }
        case CHART_DIRECTION.BottomUp:
        default: {
            var x = geom.x + geom.width / 2 - offsetX + alignmentOffsetX;
            var y = geom.y - offsetY + alignmentOffsetY;
            return {
                x: x,
                y: y,
                align: 'center',
                baseline: 'top',
                rect: {
                    x: x - valueBox.width / 2,
                    y: y,
                    width: valueBox.width,
                    height: valueBox.height,
                },
            };
        }
    }
}
function isOverflow(rect, chartDimensions, chartRotation) {
    var cWidth = chartDimensions.width;
    var cHeight = chartDimensions.height;
    if (chartRotation === 90 || chartRotation === -90) {
        cWidth = chartDimensions.height;
        cHeight = chartDimensions.width;
    }
    if (rect.x < 0 || rect.x + rect.width > cWidth) {
        return true;
    }
    if (rect.y < 0 || rect.y + rect.height > cHeight) {
        return true;
    }
    return false;
}
var DEFAULT_VALUE_COLOR = 'black';
var DEFAULT_VALUE_BORDER_COLOR = 'rgba(255, 255, 255, 0.8)';
var DEFAULT_VALUE_BORDER_SOLID_COLOR = 'rgb(255, 255, 255)';
var TRANSPARENT_COLOR = 'rgba(0,0,0,0)';
function getTextColors(fillDefinition, geometryColor, borderSize) {
    if (typeof fillDefinition === 'string') {
        return { fillColor: fillDefinition, shadowColor: TRANSPARENT_COLOR };
    }
    if ('color' in fillDefinition) {
        return {
            fillColor: fillDefinition.color,
            shadowColor: fillDefinition.borderColor || TRANSPARENT_COLOR,
        };
    }
    var fillColor = fill_text_color_1.fillTextColor(DEFAULT_VALUE_COLOR, fillDefinition.textInvertible, fillDefinition.textContrast || false, geometryColor, 'white') || DEFAULT_VALUE_COLOR;
    var defaultBorderColor = borderSize < 2 ? DEFAULT_VALUE_BORDER_COLOR : DEFAULT_VALUE_BORDER_SOLID_COLOR;
    var shadowColor = 'textBorder' in fillDefinition
        ? color_calcs_1.getTextColorIfTextInvertible(color_calcs_1.colorIsDark(fillColor), color_calcs_1.colorIsDark(defaultBorderColor), defaultBorderColor, false, geometryColor) || TRANSPARENT_COLOR
        : TRANSPARENT_COLOR;
    return {
        fillColor: fillColor,
        shadowColor: shadowColor,
    };
}
var DEFAULT_BORDER_WIDTH = 1.5;
var MAX_BORDER_WIDTH = 8;
function getTextBorderSize(fill) {
    var _a;
    if (typeof fill === 'string') {
        return DEFAULT_BORDER_WIDTH;
    }
    if ('borderWidth' in fill) {
        return Math.min((_a = fill.borderWidth) !== null && _a !== void 0 ? _a : DEFAULT_BORDER_WIDTH, MAX_BORDER_WIDTH);
    }
    var borderWidth = 'textBorder' in fill && typeof fill.textBorder === 'number' ? fill.textBorder : DEFAULT_BORDER_WIDTH;
    return Math.min(borderWidth, MAX_BORDER_WIDTH);
}
//# sourceMappingURL=bar.js.map