"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);
};
var __read = (this && this.__read) || function (o, n) {
    var m = typeof Symbol === "function" && o[Symbol.iterator];
    if (!m) return o;
    var i = m.call(o), r, ar = [], e;
    try {
        while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
    }
    catch (error) { e = { error: error }; }
    finally {
        try {
            if (r && !r.done && (m = i["return"])) m.call(i);
        }
        finally { if (e) throw e.error; }
    }
    return ar;
};
var __spread = (this && this.__spread) || function () {
    for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
    return ar;
};
Object.defineProperty(exports, "__esModule", { value: true });
var canvas_1 = require("../../../../renderers/canvas");
var constants_1 = require("../../../partition_chart/layout/utils/constants");
var measure_1 = require("../../../partition_chart/layout/utils/measure");
var constants_2 = require("../../specs/constants");
var referenceCircularSizeCap = 360;
var referenceBulletSizeCap = 500;
var barThicknessMinSizeRatio = 1 / 10;
var baselineArcThickness = 32;
var baselineBarThickness = 32;
var marginRatio = 0.05;
var maxTickFontSize = 24;
var maxLabelFontSize = 32;
var maxCentralFontSize = 38;
function get(o, name, dflt) {
    return name in o ? o[name] || dflt : dflt;
}
function renderCanvas2d(ctx, dpr, _a) {
    var config = _a.config, bulletViewModel = _a.bulletViewModel, chartCenter = _a.chartCenter;
    var _b = config;
    canvas_1.withContext(ctx, function (ctx) {
        ctx.scale(dpr, dpr);
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        ctx.translate(chartCenter.x, chartCenter.y);
        ctx.scale(1, -1);
        var subtype = bulletViewModel.subtype, lowestValue = bulletViewModel.lowestValue, highestValue = bulletViewModel.highestValue, base = bulletViewModel.base, target = bulletViewModel.target, actual = bulletViewModel.actual, bands = bulletViewModel.bands, ticks = bulletViewModel.ticks, labelMajor = bulletViewModel.labelMajor, labelMinor = bulletViewModel.labelMinor, centralMajor = bulletViewModel.centralMajor, centralMinor = bulletViewModel.centralMinor;
        var circular = subtype === constants_2.GoalSubtype.Goal;
        var vertical = subtype === constants_2.GoalSubtype.VerticalBullet;
        var domain = [lowestValue, highestValue];
        var data = __assign(__assign(__assign(__assign({ base: { value: base } }, Object.fromEntries(bands.map(function (_a, index) {
            var value = _a.value;
            return ["qualitative_" + index, { value: value }];
        }))), { target: { value: target }, actual: { value: actual }, labelMajor: { value: domain[circular || !vertical ? 0 : 1], text: labelMajor }, labelMinor: { value: domain[circular || !vertical ? 0 : 1], text: labelMinor } }), Object.assign.apply(Object, __spread([{}], ticks.map(function (_a, i) {
            var _b;
            var value = _a.value, text = _a.text;
            return (_b = {}, _b["tick_" + i] = { value: value, text: text }, _b);
        })))), (circular
            ? {
                centralMajor: { value: 0, text: centralMajor },
                centralMinor: { value: 0, text: centralMinor },
            }
            : {}));
        var minSize = Math.min(config.width, config.height);
        var referenceSize = Math.min(circular ? referenceCircularSizeCap : referenceBulletSizeCap, circular ? minSize : vertical ? config.height : config.width) *
            (1 - 2 * marginRatio);
        var barThickness = Math.min(circular ? baselineArcThickness : baselineBarThickness, referenceSize * barThicknessMinSizeRatio);
        var tickLength = barThickness * Math.pow(1 / constants_1.GOLDEN_RATIO, 3);
        var tickOffset = -tickLength / 2 - barThickness / 2;
        var tickFontSize = Math.min(maxTickFontSize, referenceSize / 25);
        var labelFontSize = Math.min(maxLabelFontSize, referenceSize / 18);
        var centralFontSize = Math.min(maxCentralFontSize, referenceSize / 14);
        var geoms = __spread(bulletViewModel.bands.map(function (b, i) { return ({
            order: 0,
            landmarks: {
                from: i ? "qualitative_" + (i - 1) : 'base',
                to: "qualitative_" + i,
            },
            aes: {
                shape: 'line',
                fillColor: b.fillColor,
                lineWidth: barThickness,
            },
        }); }), [
            {
                order: 1,
                landmarks: { from: 'base', to: 'actual' },
                aes: { shape: 'line', fillColor: 'black', lineWidth: tickLength },
            },
            {
                order: 2,
                landmarks: { at: 'target' },
                aes: { shape: 'line', fillColor: 'black', lineWidth: barThickness / constants_1.GOLDEN_RATIO },
            }
        ], bulletViewModel.ticks.map(function (b, i) { return ({
            order: 3,
            landmarks: { at: "tick_" + i },
            aes: {
                shape: 'line',
                fillColor: 'darkgrey',
                lineWidth: tickLength,
                axisNormalOffset: tickOffset,
            },
        }); }), bulletViewModel.ticks.map(function (b, i) { return ({
            order: 4,
            landmarks: { at: "tick_" + i },
            aes: {
                shape: 'text',
                textAlign: vertical ? 'right' : 'center',
                textBaseline: vertical ? 'middle' : 'top',
                fillColor: 'black',
                fontShape: { fontStyle: 'normal', fontVariant: 'normal', fontWeight: '500', fontFamily: 'sans-serif' },
                axisNormalOffset: -barThickness,
            },
        }); }), [
            {
                order: 5,
                landmarks: { at: 'labelMajor' },
                aes: {
                    shape: 'text',
                    axisNormalOffset: 0,
                    axisTangentOffset: circular || !vertical ? 0 : 2 * labelFontSize,
                    textAlign: vertical ? 'center' : 'right',
                    textBaseline: 'bottom',
                    fillColor: 'black',
                    fontShape: { fontStyle: 'normal', fontVariant: 'normal', fontWeight: '900', fontFamily: 'sans-serif' },
                },
            },
            {
                order: 5,
                landmarks: { at: 'labelMinor' },
                aes: {
                    shape: 'text',
                    axisNormalOffset: 0,
                    axisTangentOffset: circular || !vertical ? 0 : 2 * labelFontSize,
                    textAlign: vertical ? 'center' : 'right',
                    textBaseline: 'top',
                    fillColor: 'black',
                    fontShape: { fontStyle: 'normal', fontVariant: 'normal', fontWeight: '300', fontFamily: 'sans-serif' },
                },
            }
        ], (circular
            ? [
                {
                    order: 6,
                    landmarks: { at: 'centralMajor' },
                    aes: {
                        shape: 'text',
                        textAlign: 'center',
                        textBaseline: 'bottom',
                        fillColor: 'black',
                        fontShape: { fontStyle: 'normal', fontVariant: 'normal', fontWeight: '900', fontFamily: 'sans-serif' },
                    },
                },
                {
                    order: 6,
                    landmarks: { at: 'centralMinor' },
                    aes: {
                        shape: 'text',
                        textAlign: 'center',
                        textBaseline: 'top',
                        fillColor: 'black',
                        fontShape: { fontStyle: 'normal', fontVariant: 'normal', fontWeight: '300', fontFamily: 'sans-serif' },
                    },
                },
            ]
            : []));
        var maxWidth = geoms.reduce(function (p, g) { return Math.max(p, get(g.aes, 'lineWidth', 0)); }, 0);
        var r = 0.5 * referenceSize - maxWidth / 2;
        canvas_1.renderLayers(ctx, [
            function (ctx) { return canvas_1.clearCanvas(ctx, 200000, 200000); },
            function (ctx) {
                return canvas_1.withContext(ctx, function (ctx) {
                    var fullSize = referenceSize;
                    var labelSize = fullSize / 2;
                    var pxRangeFrom = -fullSize / 2 + (circular || vertical ? 0 : labelSize);
                    var pxRangeTo = fullSize / 2 + (!circular && vertical ? -2 * labelFontSize : 0);
                    var pxRangeMid = (pxRangeFrom + pxRangeTo) / 2;
                    var pxRange = pxRangeTo - pxRangeFrom;
                    var domainExtent = domain[1] - domain[0];
                    var linearScale = function (x) { return pxRangeFrom + (pxRange * (x - domain[0])) / domainExtent; };
                    var angleStart = config.angleStart, angleEnd = config.angleEnd;
                    var angleRange = angleEnd - angleStart;
                    var angleScale = function (x) { return angleStart + (angleRange * (x - domain[0])) / domainExtent; };
                    var clockwise = angleStart > angleEnd;
                    geoms
                        .slice()
                        .sort(function (a, b) { return a.order - b.order; })
                        .forEach(function (_a) {
                        var landmarks = _a.landmarks, aes = _a.aes;
                        var at = get(landmarks, 'at', '');
                        var from = get(landmarks, 'from', '');
                        var to = get(landmarks, 'to', '');
                        var textAlign = get(aes, 'textAlign', '');
                        var textBaseline = get(aes, 'textBaseline', '');
                        var fontShape = get(aes, 'fontShape', '');
                        var axisNormalOffset = get(aes, 'axisNormalOffset', 0);
                        var axisTangentOffset = get(aes, 'axisTangentOffset', 0);
                        var lineWidth = get(aes, 'lineWidth', 0);
                        var strokeStyle = get(aes, 'fillColor', '');
                        canvas_1.withContext(ctx, function (ctx) {
                            ctx.beginPath();
                            if (circular) {
                                if (aes.shape === 'line') {
                                    ctx.lineWidth = lineWidth;
                                    ctx.strokeStyle = strokeStyle;
                                    if (at) {
                                        ctx.arc(pxRangeMid, 0, r + axisNormalOffset, angleScale(data[at].value) + Math.PI / 360, angleScale(data[at].value) - Math.PI / 360, true);
                                    }
                                    else {
                                        var dataClockwise = data[from].value < data[to].value;
                                        ctx.arc(pxRangeMid, 0, r, angleScale(data[from].value), angleScale(data[to].value), clockwise === dataClockwise);
                                    }
                                }
                                else if (aes.shape === 'text') {
                                    var label = at.slice(0, 5) === 'label';
                                    var central = at.slice(0, 7) === 'central';
                                    ctx.textAlign = 'center';
                                    ctx.textBaseline = label || central ? textBaseline : 'middle';
                                    ctx.font = measure_1.cssFontShorthand(fontShape, label ? labelFontSize : central ? centralFontSize : tickFontSize);
                                    ctx.scale(1, -1);
                                    var angle = angleScale(data[at].value);
                                    if (label) {
                                        ctx.translate(0, r);
                                    }
                                    else if (!central) {
                                        ctx.translate((r - constants_1.GOLDEN_RATIO * barThickness) * Math.cos(angle), -(r - constants_1.GOLDEN_RATIO * barThickness) * Math.sin(angle));
                                    }
                                    ctx.fillText(data[at].text, 0, 0);
                                }
                            }
                            else {
                                ctx.translate(vertical ? axisNormalOffset : axisTangentOffset, vertical ? axisTangentOffset : axisNormalOffset);
                                var atPx = data[at] && linearScale(data[at].value);
                                if (aes.shape === 'line') {
                                    ctx.lineWidth = lineWidth;
                                    ctx.strokeStyle = aes.fillColor;
                                    if (at) {
                                        var atFromPx = atPx - 1;
                                        var atToPx = atPx + 1;
                                        ctx.moveTo(vertical ? 0 : atFromPx, vertical ? atFromPx : 0);
                                        ctx.lineTo(vertical ? 0 : atToPx, vertical ? atToPx : 0);
                                    }
                                    else {
                                        var fromPx = linearScale(data[from].value);
                                        var toPx = linearScale(data[to].value);
                                        ctx.moveTo(vertical ? 0 : fromPx, vertical ? fromPx : 0);
                                        ctx.lineTo(vertical ? 0 : toPx, vertical ? toPx : 0);
                                    }
                                }
                                else if (aes.shape === 'text') {
                                    ctx.textAlign = textAlign;
                                    ctx.textBaseline = textBaseline;
                                    ctx.font = measure_1.cssFontShorthand(fontShape, tickFontSize);
                                    ctx.scale(1, -1);
                                    ctx.translate(vertical ? 0 : atPx, vertical ? -atPx : 0);
                                    ctx.fillText(data[at].text, 0, 0);
                                }
                            }
                            ctx.stroke();
                        });
                    });
                });
            },
        ]);
    });
}
exports.renderCanvas2d = renderCanvas2d;
//# sourceMappingURL=canvas_renderers.js.map