export class Equalizer {
    constructor(audioElement, canvasElement) {
        this.audioElement = audioElement;
        this.canvas = canvasElement;
        this.canvasCtx = this.canvas.getContext('2d');

        this.FREQUENCIES = [60, 170, 310, 600, 1000, 3000, 6000, 12000, 14000, 16000];
        this.PRESETS = {
            flat:      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            rock:      [5, 4, -5, -8, -4, 4, 8, 9, 9, 9],
            pop:       [-2, -1, 0, 2, 4, 4, 2, 0, -1, -2],
            jazz:      [4, 3, 1, 2, -2, -2, 0, 1, 3, 4],
            classical: [5, 4, 3, -2, -3, -5, -2, 2, 4, 5],
            bass_boost:[9, 7, 4, 1, -2, -4, -4, -3, -2, -2]
        };

        this.audioCtx = null;
        this.source = null;
        this.preamp = null;
        this.filters = [];
        this.analyser = null;
        this.animationFrameId = null;
    }

    init() {
        try {
            this.audioCtx = new (window.AudioContext || window.webkitAudioContext)();
            this.source = this.audioCtx.createMediaElementSource(this.audioElement);
            
            this.preamp = this.audioCtx.createGain();

            this.filters = this.FREQUENCIES.map(freq => {
                const filter = this.audioCtx.createBiquadFilter();
                filter.type = 'peaking';
                filter.frequency.value = freq;
                filter.Q.value = 1.41;
                filter.gain.value = 0;
                return filter;
            });

            this.analyser = this.audioCtx.createAnalyser();
            this.analyser.fftSize = 256;

            // Connect nodes: source -> preamp -> filters -> analyser -> destination
            this.source.connect(this.preamp);
            let lastNode = this.preamp;
            this.filters.forEach(filter => {
                lastNode.connect(filter);
                lastNode = filter;
            });
            lastNode.connect(this.analyser);
            this.analyser.connect(this.audioCtx.destination);

            this.drawVisualizer();
            return true;
        } catch (e) {
            console.error("Error initializing Web Audio API:", e);
            return false;
        }
    }

    changeGain(bandIndex, value) {
        if (this.filters[bandIndex]) {
            this.filters[bandIndex].gain.value = value;
        }
    }

    changePreamp(value) {
        if (this.preamp) {
            this.preamp.gain.value = Math.pow(10, value / 20);
        }
    }

    applyPreset(name) {
        const values = this.PRESETS[name];
        if (!values) return;

        const bandSliders = document.querySelectorAll('.band-slider');
        values.forEach((val, i) => {
            this.changeGain(i, val);
            const slider = bandSliders[i];
            if (slider) {
                slider.value = val;
                slider.nextElementSibling.textContent = `${val} dB`;
                // GSAP animation for slider thumb
                gsap.to(slider, { 
                    duration: 0.4, 
                    value: val,
                    ease: "power2.out"
                });
            }
        });
    }

    drawVisualizer() {
        this.animationFrameId = requestAnimationFrame(() => this.drawVisualizer());
        if (!this.analyser) return;

        const bufferLength = this.analyser.frequencyBinCount;
        const dataArray = new Uint8Array(bufferLength);
        this.analyser.getByteFrequencyData(dataArray);

        this.canvasCtx.clearRect(0, 0, this.canvas.width, this.canvas.height);
        
        const barWidth = (this.canvas.width / bufferLength) * 2.5;
        let x = 0;

        for (let i = 0; i < bufferLength; i++) {
            const barHeight = dataArray[i] / 2;
            
            const r = barHeight + 25 * (i/bufferLength);
            const g = 250 * (i/bufferLength);
            const b = 50;

            this.canvasCtx.fillStyle = `rgb(${r},${g},${b})`;
            this.canvasCtx.fillRect(x, this.canvas.height - barHeight, barWidth, barHeight);
            
            x += barWidth + 1;
        }
    }

    destroy() {
        if (this.animationFrameId) {
            cancelAnimationFrame(this.animationFrameId);
        }
        if (this.audioCtx) {
            this.audioCtx.close();
        }
    }
}