var compress_buffer = require("compress-buffer");
var compress_buffer_crc32 = require("compress-buffer-crc32");
var crc_utils2 = require("crc-utils2");

var Compressor = function (configuration) {
    this._configuration = configuration;
};
    
Compressor.prototype._getCompressionRate = function(unCompressedLength, compressedLength){
    return {
        times: Math.round(unCompressedLength/compressedLength),
        percentage: Math.round((100-(100*(compressedLength/unCompressedLength)))),
        compressedLength: compressedLength,
        unCompressedLength: unCompressedLength
    };        
};

Compressor.prototype.compress = function (data, callback, compressLevel) {
    compressLevel = compressLevel || 6;
    var compressedData = compress_buffer.compress(data, compressLevel);
    callback(
        compressedData,
        this._getCompressionRate(data.length, compressedData.length)
    );
};

Compressor.prototype.uncompress = function (data, callback) {
    var compressedData = compress_buffer.uncompress(data);
    callback(
        compressedData,
        this._getCompressionRate(compressedData.length, data.length)
    );
};

Compressor.prototype.compressBLock = function (data, callback, compressLevel) {
    compressLevel = compressLevel || 6;
    var compressedData = compress_buffer_crc32.compress(data, compressLevel);
    callback(
        compressedData,
        this._getCompressionRate(data.length, compressedData.length)
    );
};

Compressor.prototype.uncompressBlock = function (data, callback) {
    var compressedData = compress_buffer_crc32.uncompress(data);
    callback(
        compressedData,
        this._getCompressionRate(compressedData.length, data.length)
    );
};

Compressor.prototype.compressBlockSync = function (data, compressLevel) {
    return compress_buffer_crc32.compress(data, compressLevel);
};

Compressor.prototype.uncompressBlockSync = function (data) {
    return compress_buffer_crc32.uncompress(data);
};

Compressor.prototype.combineBlocksSync = function (blocks) {
    var dataLength = Compressor.META.HEADER.length + Compressor.META.FOOTER.length;
    var responseEnd = 0;
    //XXX: od kazdego skompresowanego bloku odejmujemy 10 bajtow z poczatku i 10 z konca (naglowek i stopke)
    //interesuja nas tylko same dane
    var offset = 20;

    for (var i = 0; i < blocks.length; i++) {
        dataLength += blocks[i].length - offset;
    }
    var crc = crc_utils2.crc32_combine_multi(blocks);
    dataLength += crc.bufferLength.length;
    dataLength += crc.combinedCrc32.length;
    var response = new Buffer(dataLength);

    Compressor.META.HEADER.copy(response, responseEnd);
    responseEnd += Compressor.META.HEADER.length;

    for (var i = 0; i < blocks.length; i++) {
        blocks[i].slice(10, blocks[i].length - 10).copy(response, responseEnd);
        responseEnd += blocks[i].length - offset;
    }

    Compressor.META.FOOTER.copy(response, responseEnd);
    responseEnd += Compressor.META.FOOTER.length;

    crc.combinedCrc32.copy(response, responseEnd);
    responseEnd += crc.combinedCrc32.length;

    crc.bufferLength.copy(response, responseEnd);
    responseEnd += crc.bufferLength.length;

    console.info("Compressor: total: %d, last: %d", dataLength, responseEnd);
    return response;
};

Compressor.META = {};
Compressor.META.HEADER = new Buffer([0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03], "binary");
Compressor.META.FOOTER = new Buffer([0x03, 0x00], "binary");

exports.Compressor = Compressor;    
