class ProcessorDTMF extends AudioWorkletProcessor {
    constructor() {
        super();
        this.sampleRate = sampleRate;
        this.symbolDuration = 0.03; // 50 ms par symbole
        this.samplesPerSymbol = Math.floor(this.sampleRate * this.symbolDuration);
        this.encodeLowPrio = [];
        this.symbolSamples = [];
        this.lastBlackStep = 0;
        this.port.onmessage = (e) => {
            if (e.data.type === 'encode') {
                this.symbolSamples.push(...this.encodeSymbols(e.data.symbols));
                this.symbolSamples.push(...this.encodeBlack(this.sampleRate * 0.02));
            }
            if (e.data.type === 'encodeLowPrio') {
                this.encodeLowPrio.push(e.data.symbols);
            }
        };
    }

    dtmfFrequencies = [
        [697, 770, 852, 941], // Fréquences basses
        [1209, 1336, 1477, 1633] // Fréquences hautes
    ];

    encodeSymbols(symbols) {
        const samples = [];
        for (const symbol of symbols) {
            const lf = this.dtmfFrequencies[0][symbol % 4]; // Fréquence basse
            const hf = this.dtmfFrequencies[1][Math.floor(symbol / 4)]; // Fréquence haute
            // console.log(`Symbol: ${symbol}, LF: ${lf} Hz, HF: ${hf} Hz`);
            for (let i = 0; i < this.samplesPerSymbol; i++) {
                const t = i / this.sampleRate;
                const t2 = (this.lastBlackStep + i) / this.sampleRate;
                samples.push(0.5 * Math.sin(2 * Math.PI * lf * t) + 0.5 * Math.sin(2 * Math.PI * hf * t) // Signal DTMF
                    + Math.sin(2 * Math.PI * 150 * t2) * (0.0625 * (Math.sin(2 * Math.PI * 0.5 * t2) + 1))); // Ajouter un signal à 150 Hz pour le "black"
            }
            this.lastBlackStep += this.samplesPerSymbol;

            // ajouter un silence de 10 ms entre les symboles
            samples.push(...this.encodeBlack(this.sampleRate * 0.01)); // Silence
        }
        return samples;
    }

    encodeBlack(size) {
        const samples = [];

        for (let i = 0; i < size; i++) {
            const t = (this.lastBlackStep + i) / this.sampleRate;
            samples.push(Math.sin(2 * Math.PI * 150 * t) * (0.0625 * (Math.sin(2 * Math.PI * 0.5 * t) + 1))); // Signal à 350 Hz pour le "black"
        }
        this.lastBlackStep += size;
        this.lastBlackStep %= this.sampleRate * 2; // Réinitialiser tous les 2 secondes pour éviter les débordements

        return samples;
    }

    process(inputs, outputs, parameters) {
        const output = outputs[0]; // output est un tableau de canaux (ex: [Float32Array, ...])
        const channelData = output[0]; // Accéder au premier canal (mono)

        if (this.symbolSamples.length === 0 && this.encodeLowPrio.length > 0) {
            this.symbolSamples.push(...this.encodeSymbols(this.encodeLowPrio.shift()));
            this.symbolSamples.push(...this.encodeBlack(this.sampleRate * 0.02));
        }

        if (this.symbolSamples.length === 0) {
            const samples = this.encodeBlack(channelData.length)
            for (let i = 0; i < channelData.length; i++) {
                channelData[i] = samples[i] || 0;
            }
            return true;
        }

        for (let i = 0; i < channelData.length; i++) {
            channelData[i] = this.symbolSamples.shift() || 0; // Prendre le prochain échantillon ou 0 si vide
        }

        return true;
    }
}

registerProcessor('dtmf-processor', ProcessorDTMF);
