import { scaleLinear, scaleOrdinal } from 'd3-scale';
import { ColorRGBA64, parseColor } from '@ni/fast-colors';
import { WaferMapColorScaleMode } from '../types';
/**
 * Prerendering prepares render-ready dies data to be used by the rendering module
 */
export class Prerendering {
    get labelsFontSize() {
        return this._labelsFontSize;
    }
    get diesRenderInfo() {
        return this._diesRenderInfo;
    }
    constructor(wafermap) {
        this.wafermap = wafermap;
        this.fontSizeFactor = 0.8;
        this.nonHighlightedOpacity = 0.3;
        this.emptyDieColor = 'rgba(218,223,236,1)';
        this.nanDieColor = 'rgba(122,122,122,1)';
    }
    updateLabelsFontSize() {
        this._labelsFontSize = this.calculateLabelsFontSize(this.wafermap.dataManager.dieDimensions, this.wafermap.maxCharacters);
        this.updateDiesRenderInfo();
    }
    updateDiesRenderInfo() {
        this.d3ColorScale = this.createD3ColorScale(this.wafermap.colorScale, this.wafermap.colorScaleMode);
        const isDieRenderInfo = (info) => info !== null;
        if (this.wafermap.diesTable === undefined) {
            this._diesRenderInfo = this.wafermap.dies
                .map(die => this.computeDieRenderInfo(die))
                .filter(isDieRenderInfo);
        }
    }
    computeDieRenderInfo(die) {
        const margin = this.wafermap.dataManager.margin;
        const scaledX = this.wafermap.dataManager.horizontalScale(die.x);
        const scaledY = this.wafermap.dataManager.verticalScale(die.y);
        if (scaledX === undefined || scaledY === undefined) {
            return null;
        }
        return {
            x: scaledX + margin.right,
            y: scaledY + margin.top,
            fillStyle: this.calculateFillStyle(die.value, this.wafermap.colorScaleMode, this.wafermap.highlightedTags, die.tags),
            text: this.buildLabel(die.value, this.wafermap.maxCharacters, this.wafermap.dieLabelsHidden, this.wafermap.dieLabelsSuffix)
        };
    }
    calculateLabelsFontSize(dieDimensions, maxCharacters) {
        return Math.min(dieDimensions.height, (dieDimensions.width / (Math.max(2, maxCharacters) * 0.5))
            * this.fontSizeFactor);
    }
    createD3ColorScale(colorScale, colorScaleMode) {
        if (this.isColorScaleLinear(colorScaleMode)) {
            return scaleLinear()
                .domain(colorScale.values.map(item => +item))
                .range(colorScale.colors);
        }
        return scaleOrdinal()
            .domain(colorScale.values)
            .range(colorScale.colors);
    }
    dieHasData(dieData) {
        return dieData !== null && dieData !== undefined && dieData !== '';
    }
    buildLabel(value, maxCharacters, dieLabelsHidden, dieLabelsSuffix) {
        if (dieLabelsHidden || !this.dieHasData(value)) {
            return '';
        }
        const label = `${value}${dieLabelsSuffix}`;
        if (label.length >= maxCharacters) {
            return `${label.substring(0, maxCharacters)}…`;
        }
        return label;
    }
    calculateOpacity(dieTags, highlightedTags) {
        if (!highlightedTags || highlightedTags.length === 0) {
            return 1;
        }
        const highlightedSet = new Set(highlightedTags);
        if (dieTags?.some(dieTag => highlightedSet.has(dieTag))) {
            return 1;
        }
        return this.nonHighlightedOpacity;
    }
    isColorScaleLinear(colorScaleMode) {
        return colorScaleMode === WaferMapColorScaleMode.linear;
    }
    isColorScaleOrdinal(colorScaleMode) {
        return colorScaleMode === WaferMapColorScaleMode.ordinal;
    }
    calculateFillStyle(value, colorScaleMode, highlightedTags, dieTags) {
        let colorValue = this.emptyDieColor;
        if (this.dieHasData(value)) {
            if (isNaN(+value)) {
                colorValue = this.nanDieColor;
            }
            else if (this.isColorScaleLinear(colorScaleMode)) {
                colorValue = this.d3ColorScale(+value);
            }
            else if (this.isColorScaleOrdinal(colorScaleMode)) {
                colorValue = this.d3ColorScale(value);
            }
        }
        if (colorValue === undefined) {
            return this.emptyDieColor;
        }
        let rgbColor = parseColor(colorValue);
        if (rgbColor === null) {
            return this.emptyDieColor;
        }
        rgbColor = new ColorRGBA64(rgbColor.r, rgbColor.g, rgbColor.b, this.calculateOpacity(dieTags, highlightedTags));
        return rgbColor.toStringWebRGBA();
    }
}
//# sourceMappingURL=prerendering.js.map