"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.genAchievementProgressBar = genAchievementProgressBar;
exports.genAchievementTextAndAvatar = genAchievementTextAndAvatar;
const canvas_1 = require("@napi-rs/canvas");
const errors_1 = require("../errors");
const canvas_2 = require("../utils/canvas");
const text_1 = require("../utils/text");
const validation_1 = require("../utils/validation");
const RARITY_COLORS = {
    common: '#9B9B9B',
    rare: '#4E9AFF',
    epic: '#BF5FFF',
    legendary: '#FFB800',
};
function genAchievementProgressBar(options) {
    if (!options.rankData) {
        throw new errors_1.KythiaArtsError('rankData is required for genAchievementProgressBar');
    }
    const { currentXp, requiredXp, barColor, xpBarHeight = 38, xpBarStyle = 'capsule', barGradientDirection = 'horizontal', barBorder, } = options.rankData;
    const { width, height, scaleX, scaleY } = (0, canvas_2.getCanvasDimensions)(options);
    const minScale = Math.min(scaleX, scaleY);
    const canvas = (0, canvas_1.createCanvas)(width, height);
    const ctx = canvas.getContext('2d');
    const alphaValue = 0.45;
    const barWidthTotal = 540 * scaleX;
    const barHeight = xpBarHeight * scaleY;
    const barX = 304 * scaleX;
    const barY = 224 * scaleY;
    const barRadius = xpBarStyle === 'sharp'
        ? 0
        : xpBarStyle === 'capsule'
            ? barHeight / 2
            : 14 * minScale;
    ctx.globalAlpha = alphaValue;
    ctx.fillStyle = '#000';
    ctx.beginPath();
    ctx.roundRect(barX, barY, barWidthTotal, barHeight, [barRadius]);
    ctx.fill();
    ctx.globalAlpha = 1;
    if (barBorder?.width && barBorder?.color) {
        ctx.strokeStyle = (0, validation_1.parseHex)(barBorder.color);
        ctx.lineWidth = barBorder.width * minScale;
        ctx.beginPath();
        ctx.roundRect(barX, barY, barWidthTotal, barHeight, [barRadius]);
        ctx.stroke();
    }
    const safeRequiredXp = requiredXp === 0 ? 1 : requiredXp;
    if (requiredXp > 0) {
        const barColors = [];
        if (typeof barColor === 'string') {
            barColors.push(barColor);
        }
        else if (Array.isArray(barColor)) {
            barColors.push(...barColor);
        }
        let barWidth = Math.round((currentXp * barWidthTotal) / safeRequiredXp);
        barWidth = Math.min(barWidth, barWidthTotal);
        if (barWidth > 0 && barWidth < barHeight) {
            barWidth = barHeight;
        }
        ctx.save();
        ctx.beginPath();
        ctx.roundRect(barX, barY, barWidthTotal, barHeight, [barRadius]);
        ctx.clip();
        let gradientCoords = {
            x0: barX,
            y0: barY,
            x1: barX + barWidthTotal,
            y1: barY,
        };
        if (barGradientDirection === 'vertical') {
            gradientCoords = {
                x0: barX,
                y0: barY,
                x1: barX,
                y1: barY + barHeight,
            };
        }
        const grd = ctx.createLinearGradient(gradientCoords.x0, gradientCoords.y0, gradientCoords.x1, gradientCoords.y1);
        for (let i = 0; i < barColors.length; i++) {
            const stop = i / (barColors.length - 1);
            const color = barColors[i];
            if (color) {
                grd.addColorStop(stop, (0, validation_1.parseHex)(color));
            }
        }
        ctx.fillStyle = barColors.length > 0 ? grd : '#fff';
        ctx.beginPath();
        ctx.roundRect(barX, barY, barWidth, barHeight, [barRadius]);
        ctx.fill();
        ctx.restore();
    }
    let xpText = '';
    if (requiredXp > 0) {
        xpText = `${(0, text_1.abbreviateNumber)(currentXp)} / ${(0, text_1.abbreviateNumber)(requiredXp)} ACHIEVEMENTS`;
    }
    else {
        xpText = `${(0, text_1.abbreviateNumber)(currentXp)} ACHIEVEMENTS`;
    }
    const customFont = options?.customFont ?? 'Helvetica';
    const weight = options?.fontWeight ?? 'bold';
    ctx.font = `${weight} ${18 * minScale}px ${customFont}`;
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.shadowColor = 'rgba(0, 0, 0, 0.8)';
    ctx.shadowBlur = 4 * minScale;
    ctx.shadowOffsetX = 0;
    ctx.shadowOffsetY = 1 * minScale;
    ctx.fillStyle = '#ffffff';
    ctx.fillText(xpText, barX + barWidthTotal / 2, barY + barHeight / 2 + 1.5 * scaleY);
    ctx.shadowColor = 'transparent';
    ctx.shadowBlur = 0;
    ctx.shadowOffsetX = 0;
    ctx.shadowOffsetY = 0;
    ctx.textBaseline = 'alphabetic';
    return canvas;
}
async function genAchievementTextAndAvatar(data, options, avatarData, hasFrame = false) {
    const { width, height, scaleX, scaleY } = (0, canvas_2.getCanvasDimensions)(options);
    const minScale = Math.min(scaleX, scaleY);
    const canvas = (0, canvas_1.createCanvas)(width, height);
    const ctx = canvas.getContext('2d');
    const customFont = options?.customFont ?? 'Helvetica';
    const weight = options?.fontWeight ?? 'bold';
    const accentHex = options.accentColor ??
        RARITY_COLORS[options.rarity ?? 'common'] ??
        '#9B9B9B';
    const textX = 300 * scaleX;
    const textMaxWidth = width - textX - 40 * scaleX;
    let rarityOffset = 0;
    if (!options.hideRarity && options.rarity) {
        const rarityLabel = options.rarity.charAt(0).toUpperCase() + options.rarity.slice(1);
        const pillFont = `${18 * minScale}px ${customFont}`;
        ctx.font = pillFont;
        const pillW = ctx.measureText(rarityLabel).width + 20 * minScale;
        const pillH = 26 * minScale;
        const pillX = textX;
        const pillY = 30 * scaleY;
        ctx.globalAlpha = 0.2;
        ctx.fillStyle = accentHex;
        ctx.beginPath();
        ctx.roundRect(pillX, pillY, pillW, pillH, [pillH / 2]);
        ctx.fill();
        ctx.globalAlpha = 1;
        ctx.fillStyle = accentHex;
        ctx.textAlign = 'left';
        ctx.fillText(rarityLabel, pillX + 10 * minScale, pillY + pillH * 0.72);
        rarityOffset = 25 * scaleY;
    }
    const baseNameY = options.hideRarity || !options.rarity ? 100 : 85;
    const nameY = baseNameY * scaleY + rarityOffset;
    ctx.font = `${weight} ${55 * minScale}px ${customFont}`.trim();
    ctx.fillStyle = '#FFFFFF';
    ctx.textAlign = 'left';
    const { username: achievementName } = (0, text_1.parseUsername)(options.achievementName ?? 'Achievement Unlocked', ctx, customFont, 55 * minScale, textMaxWidth, weight);
    ctx.fillText(achievementName, textX, nameY);
    const descY = nameY + 30 * scaleY;
    const rawDesc = options.achievementDesc ?? '';
    ctx.font = `${22 * minScale}px ${customFont}`;
    let descText = rawDesc;
    while (ctx.measureText(descText).width > textMaxWidth &&
        descText.length > 0) {
        descText = descText.slice(0, -1);
    }
    if (descText.length < rawDesc.length)
        descText = `${descText.slice(0, -3)}...`;
    ctx.fillStyle = '#b0b3b8';
    ctx.fillText(descText, textX, descY);
    if (!options.hideUser) {
        const displayName = options.customUsername ?? data.global_name ?? data.username ?? 'Unknown';
        const userY = descY + 28 * scaleY;
        ctx.font = `${20 * minScale}px ${customFont}`;
        ctx.fillStyle = '#72767d';
        ctx.fillText('Achievement unlocked by ', textX, userY);
        const prefixW = ctx.measureText('Achievement unlocked by ').width;
        ctx.fillStyle = '#dadada';
        ctx.font = `${weight} ${20 * minScale}px ${customFont}`.trim();
        ctx.fillText(displayName, textX + prefixW, userY);
    }
    const cardAvatar = await (0, canvas_1.loadImage)(avatarData);
    const roundValue = (options?.squareAvatar ? 30 : 225) * minScale;
    const newCenterX = 159.5 * scaleX;
    const newCenterY = 151.5 * scaleY;
    const avatarSize = 225 * minScale;
    const avatarX = newCenterX - avatarSize / 2;
    const avatarY = newCenterY - avatarSize / 2;
    ctx.save();
    ctx.beginPath();
    ctx.roundRect(avatarX, avatarY, avatarSize, avatarSize, [roundValue]);
    ctx.clip();
    ctx.fillStyle = '#292b2f';
    ctx.fill();
    ctx.drawImage(cardAvatar, avatarX, avatarY, avatarSize, avatarSize);
    ctx.restore();
    if (!hasFrame) {
        ctx.strokeStyle = (0, validation_1.parseHex)(accentHex);
        ctx.lineWidth = 2.5 * minScale;
        ctx.beginPath();
        ctx.roundRect(avatarX, avatarY, avatarSize, avatarSize, [roundValue]);
        ctx.stroke();
    }
    if (options.achievementEmoji) {
        const badgeX = newCenterX + 52.5 * minScale;
        const badgeY = newCenterY + 52.5 * minScale;
        const badgeSize = 62 * minScale;
        ctx.globalCompositeOperation = 'destination-out';
        ctx.beginPath();
        ctx.roundRect(badgeX, badgeY, badgeSize, badgeSize, [62 * minScale]);
        ctx.fill();
        ctx.globalCompositeOperation = 'source-over';
        if (!options.achievementEmoji.startsWith('http')) {
            ctx.globalAlpha = 1;
            ctx.fillStyle = '#1e1f23';
            ctx.beginPath();
            ctx.roundRect(badgeX, badgeY, badgeSize, badgeSize, [62 * minScale]);
            ctx.fill();
            ctx.font = `${badgeSize * 0.65}px ${customFont}`;
            ctx.textAlign = 'center';
            ctx.textBaseline = 'middle';
            ctx.fillStyle = '#FFFFFF';
            ctx.fillText(options.achievementEmoji, badgeX + badgeSize / 2, badgeY + badgeSize / 2);
            ctx.textBaseline = 'alphabetic';
        }
        else {
            const icon = await (0, canvas_1.loadImage)(options.achievementEmoji).catch(() => undefined);
            if (icon) {
                ctx.save();
                ctx.beginPath();
                ctx.roundRect(badgeX, badgeY, badgeSize, badgeSize, [62 * minScale]);
                ctx.clip();
                ctx.drawImage(icon, badgeX, badgeY, badgeSize, badgeSize);
                ctx.restore();
            }
        }
    }
    return canvas;
}
//# sourceMappingURL=achievement.js.map