package io.domisum.lib.auxiliumlib.util;

import io.domisum.lib.auxiliumlib.annotations.API;
import io.domisum.lib.auxiliumlib.exceptions.ProgrammingError;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.Validate;

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

@API
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class CompressionUtil
{
	
	// CONSTANTS
	private static final int BUFFER_SIZE = 1024;
	
	
	// COMPRESSION
	@API
	public static byte[] compress(byte[] input)
	{
		return compress(input, Speed.BALANCED);
	}
	
	@API
	public static byte[] compress(byte[] input, Speed compressionSpeed)
	{
		Validate.notNull(input);
		Validate.notNull(compressionSpeed);
		
		var compressor = new Deflater();
		compressor.setLevel(compressionSpeed.deflaterLevel);
		compressor.setInput(input);
		compressor.finish();
		try(var outputStream = new ByteArrayOutputStream(input.length))
		{
			byte[] buffer = new byte[BUFFER_SIZE];
			
			while(!compressor.finished())
				outputStream.write(buffer, 0, compressor.deflate(buffer));
			
			return outputStream.toByteArray();
		}
		catch(IOException e)
		{
			throw new ProgrammingError(e);
		}
	}
	
	@API
	public static byte[] decompress(byte[] input)
	{
		Validate.notNull(input);
		
		var decompressor = new Inflater();
		decompressor.setInput(input);
		try(var outputStream = new ByteArrayOutputStream(input.length))
		{
			byte[] buffer = new byte[BUFFER_SIZE];
			while(!decompressor.finished())
				outputStream.write(buffer, 0, decompressor.inflate(buffer));
			
			outputStream.close();
			return outputStream.toByteArray();
		}
		catch(DataFormatException e)
		{
			throw new IllegalArgumentException("Invalid data provided", e);
		}
		catch(IOException e)
		{
			throw new ProgrammingError(e);
		}
	}
	
	
	@API
	public enum Speed
	{
		
		FAST(Deflater.BEST_SPEED),
		BALANCED((Deflater.BEST_COMPRESSION+Deflater.BEST_SPEED)/2),
		QUALITY(Deflater.BEST_COMPRESSION);
		
		
		// ATTRIBUTES
		private final int deflaterLevel;
		
		
		// INIT
		Speed(int deflaterLevel)
		{
			this.deflaterLevel = deflaterLevel;
		}
		
	}
	
}

@@ -849,25 +849,23 @@
 %09%0A%09%09var 
-compresso
+deflate
 r = new 
@@ -874,33 +874,31 @@
 flater();%0A%09%09
-compresso
+deflate
 r.setLevel(c
@@ -931,25 +931,23 @@
 vel);%0A%09%09
-compresso
+deflate
 r.setInp
@@ -959,25 +959,23 @@
 put);%0A%09%09
-compresso
+deflate
 r.finish
@@ -1104,25 +1104,23 @@
 %09while(!
-compresso
+deflate
 r.finish
@@ -1159,25 +1159,23 @@
 fer, 0, 
-compresso
+deflate
 r.deflat
@@ -1293,24 +1293,61 @@
 ror(e);%0A%09%09%7D%0A
+%09%09finally%0A%09%09%7B%0A%09%09%09deflater.end();%0A%09%09%7D%0A
 %09%7D%0A%09%0A%09@API%0A%09
@@ -1431,27 +1431,23 @@
 %09%0A%09%09var 
-decompresso
+inflate
 r = new 
@@ -1460,27 +1460,23 @@
 er();%0A%09%09
-decompresso
+inflate
 r.setInp
@@ -1608,27 +1608,23 @@
 %09while(!
-decompresso
+inflate
 r.finish
@@ -1667,19 +1667,15 @@
  0, 
-decompresso
+inflate
 r.in
@@ -1698,33 +1698,8 @@
 %09%09%09%0A
-%09%09%09outputStream.close();%0A
 %09%09%09r
@@ -1903,24 +1903,61 @@
 ror(e);%0A%09%09%7D%0A
+%09%09finally%0A%09%09%7B%0A%09%09%09inflater.end();%0A%09%09%7D%0A
 %09%7D%0A%09%0A%09%0A%09@API

Add inflater and deflater calls to end