/*
     This file is part of GNUnet.
     (C) 2009,2013 Christian Grothoff (and other contributing authors)

     GNUnet is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published
     by the Free Software Foundation; either version 2, or (at your
     option) any later version.

     GNUnet is distributed in the hope that it will be useful, but
     WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     General Public License for more details.

     You should have received a copy of the GNU General Public License
     along with GNUnet; see the file COPYING.  If not, write to the
     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
     Boston, MA 02111-1307, USA.
 */
package org.gnunet.testbed;

import com.google.common.base.Charsets;
import org.gnunet.util.Configuration;

import java.io.ByteArrayOutputStream;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.Inflater;

/**
 * A configuration stored in compressed form.
 */
public class CompressedConfig {
    final public byte[] compressedData;

    private int uncompressedSize;

    /**
     * Create a compressed configuration from an uncompressed configuration.
     * @param cfg the uncompressed configuration
     */
    public CompressedConfig(Configuration cfg) {
        byte[] serializedConfig = cfg.serialize().getBytes();

        Deflater compresser = new Deflater();
        compresser.setInput(serializedConfig);
        compresser.finish();

        ByteArrayOutputStream s = new ByteArrayOutputStream();
        byte[] buf = new byte[1024];
        while (!compresser.finished()) {
            int n = compresser.deflate(buf);
            s.write(buf, 0, n);
        }
        compressedData = s.toByteArray();
        uncompressedSize = serializedConfig.length;
    }

    /**
     * Create a compressed configuration from already compressed data.
     * @param compressedData the compressed config data
     */
    public CompressedConfig(byte[] compressedData) {
        this.compressedData = compressedData;
        this.uncompressedSize = -1;
    }

    /**
     * Decompress the configuration.
     *
     * @return the decompressed configuration, or null on data format error
     */
    public Configuration decompress() {
        Inflater inflater = new Inflater();
        inflater.setInput(compressedData);
        ByteArrayOutputStream s = new ByteArrayOutputStream();
        byte[] buf = new byte[1024];
        while (!inflater.finished()) {
            int n;
            try {
                n = inflater.inflate(buf);
            } catch (DataFormatException e) {
                return null;
            }
            s.write(buf, 0, n);
        }
        String str = new String(s.toByteArray(), Charsets.UTF_8);
        Configuration cfg = new Configuration();
        cfg.deserialize(str);
        return cfg;
    }

    public int getUncompressedSize() {
        if (uncompressedSize == -1) {
            uncompressedSize = decompress().serialize().getBytes().length;
        }
        return uncompressedSize;
    }
}
