/*
 * Copyright (c) eHealth
 */
package be.ehealth.technicalconnector.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Arrays;
import java.util.zip.Deflater;
import java.util.zip.DeflaterInputStream;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import org.apache.commons.io.IOUtils;
import org.bouncycastle.util.encoders.Base64;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

import be.ehealth.technicalconnector.config.ConfigFactory;


/**
 * Test class which evaluates the differents compression algorithmes
 * 
 * @author EHP
 */
public class ConnectorIOUtilsTest {

    @BeforeClass
    public static void init() throws Exception {
        ConfigFactory.getConfigValidator().getConfig();
    }

    /**
     * Unit test to ensure backwards compability between version 2 of the connector.
     * 
     * @author EHP
     */
    @Test
    public void testDecompressionGzip() throws Exception {

        byte[] in = "ehealthplatform".getBytes();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        GZIPOutputStream gzipos = new GZIPOutputStream(baos);
        gzipos.write(in);
        gzipos.flush();
        baos.flush();
        gzipos.close();
        baos.close();
        byte[] gzipin = baos.toByteArray();


        byte[] result = ConnectorIOUtils.decompress(gzipin);

        Assert.assertEquals(new String(in), new String(result));
    }

    /**
     * Unit test to ensure backwards compability between version 2 of the connector.
     * 
     * @author EHP
     */
    @Test
    public void testCompressionGzip() throws Exception {
        byte[] in = "ehealthplatform".getBytes();
        byte[] out = ConnectorIOUtils.compress(in);

        GZIPInputStream input = new GZIPInputStream(new ByteArrayInputStream(out));
        byte[] result = ConnectorIOUtils.getBytes(input);

        Assert.assertEquals(new String(in), new String(result));
    }

    @Test
    public void testDecompressionZlib() throws Exception {

        byte[] in = "ehealthplatform".getBytes();
        Deflater compresser = new Deflater(Deflater.DEFAULT_COMPRESSION, true);
        compresser.setInput(in);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        compresser.finish();

        byte[] buffer = new byte[1024];
        while (!compresser.finished()) {
            int count = compresser.deflate(buffer);
            outputStream.write(buffer, 0, count);
        }
        outputStream.close();
        byte[] comout = outputStream.toByteArray();
        compresser.end();


        byte[] result = ConnectorIOUtils.decompress(comout);
        // result = ConnectorIOUtils.getBytes(is);
        Assert.assertEquals(new String(in), new String(result));
    }

    @Test
    public void testCompressionDEFLATER() throws Exception {

        StringBuilder sb = new StringBuilder("ehealthplatform 12345567890\n |é#'(§è!ççà einde string");

        final String inputString = sb.toString();
        byte[] original = inputString.getBytes();

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        Deflater deflater = new Deflater(Deflater.DEFAULT_COMPRESSION, true);
        DeflaterInputStream deflateInputStream = new DeflaterInputStream(new ByteArrayInputStream(original), deflater);
        IOUtils.copy(deflateInputStream, bos);

        bos.flush();
        bos.close();
        byte[] expected = bos.toByteArray();

        byte[] actual = ConnectorIOUtils.compress(original, ConnectorIOUtils.COMPRESSION_ALGO_DEFLATE);
        Assert.assertEquals(new String(expected), new String(actual));

        // test decompres with result compression
        byte[] compressedDecompressed = ConnectorIOUtils.decompress(ConnectorIOUtils.compress(original, ConnectorIOUtils.COMPRESSION_ALGO_DEFLATE));
        String resultString = new String(compressedDecompressed);
        Assert.assertEquals(inputString, resultString);
        Assert.assertEquals(compressedDecompressed.length, original.length);
        Assert.assertTrue(Arrays.equals(compressedDecompressed, original));
    }


    @Test
    public void testDeCompressionDEFLATER() throws Exception {


        byte[] in = "ehealthplatform".getBytes();

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        DeflaterOutputStream gzipos = new DeflaterOutputStream(baos, new Deflater(Deflater.DEFAULT_COMPRESSION, true));
        gzipos.write(in);
        gzipos.flush();
        baos.flush();
        gzipos.close();
        baos.close();
        byte[] compressed = baos.toByteArray();


        byte[] actual = ConnectorIOUtils.decompress(compressed);


        Assert.assertEquals(new String(in), new String(actual));


    }

    @Test
    public void testBase64DecodeEmptyArray() throws Exception {
        byte[] base64Decode = ConnectorIOUtils.base64Decode("".getBytes(), false);
        Assert.assertNotNull(base64Decode);
    }

    @Test
    public void testBase64DecodeArrayWithLength1ReturnsWithoutDecoding() throws Exception {
        String original = "a";
        byte[] base64Decode = ConnectorIOUtils.base64Decode(original.getBytes(), false);
        Assert.assertNotNull(base64Decode);
        Assert.assertArrayEquals(original.getBytes(), base64Decode);
    }

    @Test
    public void testBase64DecodeArrayWithLength2ReturnsWithoutDecoding() throws Exception {
        String original = "ab";
        byte[] base64Decode = ConnectorIOUtils.base64Decode(original.getBytes(), false);
        Assert.assertNotNull(base64Decode);
        Assert.assertArrayEquals(original.getBytes(), base64Decode);
    }

    @Test
    public void testBase64DecodeArrayWithLength3ReturnsWithoutDecoding() throws Exception {
        String original = "abc";
        byte[] base64Decode = ConnectorIOUtils.base64Decode(original.getBytes(), false);
        Assert.assertNotNull(base64Decode);
        Assert.assertArrayEquals(original.getBytes(), base64Decode);
    }

    @Test
    public void testBase64DecodeArrayWithLength4() throws Exception {
        String original = "abcd";
        byte[] base64Decode = ConnectorIOUtils.base64Decode(original.getBytes(), false);
        Assert.assertNotNull(base64Decode);
        Assert.assertArrayEquals(original.getBytes(), Base64.encode(base64Decode));
    }

    @Test
    public void testBase64DecodeArrayWithLength5ReturnsWithoutDecoding() throws Exception {
        String original = "abcde";
        byte[] base64Decode = ConnectorIOUtils.base64Decode(original.getBytes(), false);
        Assert.assertNotNull(base64Decode);
        Assert.assertEquals(original, new String(base64Decode));
        Assert.assertArrayEquals(original.getBytes(), base64Decode);
    }


}
