// FLAC worker for encoding audio using libflac.js

importScripts('libflac.js');

var flacEncoder;
var FLAC_INITIALIZED = false;
var sample_rate = 44100;
var compression = 5; // Default compression (0-8)
var channels = 1;
var buffers = [];
var bufIndex = 0;
var first_buffer = true;
var samples_left = null;
var samples_right = null;

function convert(n) {
    var v = n < 0 ? n * 32768 : n * 32767;
    return Math.max(-32768, Math.min(32768, v));
}

function initFLAC() {
    if (FLAC_INITIALIZED) return true;
    
    //                                        SAMPLERATE, CHANNELS, BPS, COMPRESSION, 0, VERIFY, BLOCK_SIZE);
    flacEncoder = Flac.create_libflac_encoder(sample_rate, channels, 16, compression, 0, true, 0);
    if (flacEncoder != 0) {
        var status = Flac.init_encoder_stream(flacEncoder, function(buffer, bytes) {
            buffers.push(new Uint8Array(buffer));
            bufIndex += buffer.byteLength;
        });
        
        FLAC_INITIALIZED = true;
        return status == 0;
    }
    
    return false;
}

function interleave(inputL, inputR) {
    var length = inputL.length + inputR.length;
    var result = new Int32Array(length);

    var index = 0,
        inputIndex = 0;

    while (index < length) {
        result[index++] = inputL[inputIndex];
        result[index++] = inputR[inputIndex];
        ++inputIndex;
    }
    return result;
}

onmessage = function(ev) {
    if (!ev.data) return;

    if (ev.data.sample_rate) {
        sample_rate = ev.data.sample_rate / 1;
        compression = ev.data.flac_compression;
        channels = ev.data.channels / 1;
        
        initFLAC();
        return;
    }

    if (first_buffer) {
        samples_left = new Int16Array(ev.data, 0);
        first_buffer = false;

        if (channels > 1) return;
    }

    if (ev.data && channels > 1) {
        samples_right = new Int16Array(ev.data, 0);
    }

    if (!FLAC_INITIALIZED) {
        postMessage({percentage: 0});
        return;
    }

    // Progress update
    postMessage({percentage: 50});

    // Process the audio data
    var interleaved = null;
    var samples = null;
    
    if (channels > 1) {
        // Create interleaved buffer for stereo
        interleaved = interleave(samples_left, samples_right);
        samples = interleaved;
    } else {
        // Use mono buffer directly
        samples = samples_left;
    }

    // Encode the audio data
    if (channels > 1) {
        Flac.FLAC__stream_encoder_process_interleaved(flacEncoder, samples, samples_left.length);
    } else {
        var tmp_samples = new Int32Array(samples_left.length);
        var tmp_index = 0;
        while (tmp_index < samples_left.length) {
            tmp_samples[tmp_index] = samples_left[tmp_index];
            ++tmp_index;
        }
        Flac.FLAC__stream_encoder_process(flacEncoder, [tmp_samples], samples_left.length);
    }
    
    // Finish encoding
    Flac.FLAC__stream_encoder_finish(flacEncoder);

    // Combine all buffers into a single Uint8Array
    var outputData = new Uint8Array(bufIndex);
    var offset = 0;
    for (var i = 0; i < buffers.length; i++) {
        outputData.set(buffers[i], offset);
        offset += buffers[i].length;
    }
    
    // Create blob and return
    var blob = new Blob([outputData], {type: 'audio/flac'});
    postMessage(blob);
    
    // Clean up
    Flac.FLAC__stream_encoder_delete(flacEncoder);
    FLAC_INITIALIZED = false;
    buffers = [];
    bufIndex = 0;
}