class Gauge extends HTMLElement {
    constructor(iconName, label, description) {
        super();

        this.iconName = iconName;
        this.label = label;
        this.description = description;
    }

    connectedCallback() {
        this.role = "progressbar";
        this.classList.add("icon", `icon-${this.iconName}`);

        this.full = this.appendChild(document.createElement("div"));
        this.full.classList.add("full", "icon", `icon-${this.iconName}-white`);

        this.normalizedValue = 0;
        this.updateVisibility();
    }

    setValue(value, valueMax) {
        let clampedNormalized = Math.max(0, Math.min(1, value / valueMax));
        this.normalizedValue = clampedNormalized;
        this.style.setProperty("--progress", `${clampedNormalized * 100}%`);
        this.title = `${this.label}: ${value} / ${valueMax} (${Math.ceil(clampedNormalized * 100)}%)\n${this.description}`;
        this.updateVisibility();
    }

    updateVisibility() {
        this.visible = this.normalizedValue > 0.25;
        if (!this.visible) this.classList.add("hidden");
        else this.classList.remove("hidden");
    }
}

customElements.define("rkgk-brush-cost-gauge", Gauge);

export class BrushCostGauges extends HTMLElement {
    constructor() {
        super();
    }

    connectedCallback() {
        this.codeSizeGauge = this.appendChild(
            createGauge({
                className: "code-size",
                iconName: "brackets",
                label: "Code size",
                description:
                    "How large your code is.\n" +
                    "The more syntactic elements there are, the bigger it gets!\n" +
                    "Note that this is not the same as the character count.",
            }),
        );
        this.fuelGauge = this.appendChild(
            createGauge({
                className: "fuel",
                iconName: "droplet",
                label: "Fuel",
                description:
                    "How long your code runs.\n" +
                    "The longer it runs, the more fuel it consumes!\n" +
                    "Remember that built-in functions are cheaper than ones you write yourself.",
            }),
        );
        this.memoryGauge = this.appendChild(
            createGauge({
                className: "memory",
                iconName: "memory",
                label: "Memory",
                description:
                    "How much memory your code uses.\n" +
                    "This includes a baseline amount of memory for temporary data.\n" +
                    "Excessive list transformations can fill up your memory very quickly!",
            }),
        );

        this.codeSizeGauge.setValue(0);
        this.fuelGauge.setValue(0);
        this.memoryGauge.setValue(0);
    }

    update(stats) {
        this.codeSizeGauge.setValue(stats.astSize, stats.astSizeMax);
        this.fuelGauge.setValue(stats.fuel, stats.fuelMax);
        this.memoryGauge.setValue(stats.memory, stats.memoryMax);

        let visible =
            this.codeSizeGauge.visible || this.fuelGauge.visible || this.memoryGauge.visible;
        if (!visible) this.classList.add("hidden");
        else this.classList.remove("hidden");
    }
}

customElements.define("rkgk-brush-cost-gauges", BrushCostGauges);

function createGauge({ className, iconName, label, description }) {
    let gauge = new Gauge(iconName, label, description);
    gauge.classList.add(className);
    return gauge;
}
