package com.palacesun.engine.maskingtool;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;

public class ZLibUtils {
   public static String compressStr(String data) {
      byte[] dataBytesArr = data.getBytes();
      byte[] reDataBytesArr = compress(dataBytesArr);
      String str = byteArrToBinStr(reDataBytesArr);
      return str;
   }

   public static String decompressStr(String data) {
      byte[] dataBytesArr = binStrToByteArr(data);
      byte[] reDataBytesArr = decompress(dataBytesArr);
      String str = new String(reDataBytesArr);
      return str;
   }

   public static String byteArrToBinStr(byte[] b) {
      StringBuffer result = new StringBuffer();

      for(int i = 0; i < b.length; ++i) {
         String bit = Long.toString((long)(b[i] & 255), 2);
         int len = 8 - bit.length();

         for(int j = 0; j < len; ++j) {
            bit = "0" + bit;
         }

         result.append(bit);
      }

      return result.toString();
   }

   public static byte[] binStrToByteArr(String binStr) {
      int len = binStr.length() / 8;
      byte[] b = new byte[len];

      for(int i = 0; i < len; ++i) {
         b[i] = Long.valueOf(binStr.substring(i * 8, (i + 1) * 8), 2).byteValue();
      }

      return b;
   }

   public static byte[] binStrToByteArr11(String binStr) {
      String[] temp = binStr.split(",");
      byte[] b = new byte[temp.length];

      for(int i = 0; i < b.length; ++i) {
         b[i] = Long.valueOf(temp[i], 2).byteValue();
      }

      return b;
   }

   public static void main(String[] args) {
      decompressStr(compressStr("abc"));
   }

   public static byte[] compress(byte[] data) {
      byte[] output = new byte[0];
      Deflater compresser = new Deflater();
      compresser.reset();
      compresser.setInput(data);
      compresser.finish();
      ByteArrayOutputStream bos = new ByteArrayOutputStream(data.length);

      try {
         byte[] buf = new byte[1024];

         while(!compresser.finished()) {
            int i = compresser.deflate(buf);
            bos.write(buf, 0, i);
         }

         output = bos.toByteArray();
      } catch (Exception e) {
         output = data;
         e.printStackTrace();
      } finally {
         try {
            bos.close();
         } catch (IOException e) {
            e.printStackTrace();
         }

      }

      compresser.end();
      return output;
   }

   public static void compress(byte[] data, OutputStream os) {
      DeflaterOutputStream dos = new DeflaterOutputStream(os);

      try {
         dos.write(data, 0, data.length);
         dos.finish();
         dos.flush();
      } catch (IOException e) {
         e.printStackTrace();
      }

   }

   public static byte[] decompress(byte[] data) {
      byte[] output = new byte[0];
      Inflater decompresser = new Inflater();
      decompresser.reset();
      decompresser.setInput(data);
      ByteArrayOutputStream o = new ByteArrayOutputStream(data.length);

      try {
         byte[] buf = new byte[1024];

         while(!decompresser.finished()) {
            int i = decompresser.inflate(buf);
            o.write(buf, 0, i);
         }

         output = o.toByteArray();
      } catch (Exception e) {
         output = data;
         e.printStackTrace();
      } finally {
         try {
            o.close();
         } catch (IOException e) {
            e.printStackTrace();
         }

      }

      decompresser.end();
      return output;
   }

   public static byte[] decompress(InputStream is) {
      InflaterInputStream iis = new InflaterInputStream(is);
      ByteArrayOutputStream o = new ByteArrayOutputStream(1024);

      try {
         int i = 1024;
         byte[] buf = new byte[i];

         while((i = iis.read(buf, 0, i)) > 0) {
            o.write(buf, 0, i);
         }
      } catch (IOException e) {
         e.printStackTrace();
      }

      return o.toByteArray();
   }

   public static String BinstrToStr(String binStr) {
      char[] tempChar = new char[binStr.length() / 8];
      int n = 0;

      for(int i = 0; i < binStr.length(); i += 8) {
         String bit = binStr.substring(i, i + 8);
         tempChar[n] = BinstrToChar(bit);
         ++n;
      }

      String bitStr = String.valueOf(tempChar);
      return bitStr;
   }

   public static char BinstrToChar(String binStr) {
      int[] temp = BinstrToIntArray(binStr);
      int sum = 0;

      for(int i = 0; i < temp.length; ++i) {
         sum += temp[temp.length - 1 - i] << i;
      }

      return (char)sum;
   }

   public static int[] BinstrToIntArray(String binStr) {
      char[] temp = binStr.toCharArray();
      int[] result = new int[temp.length];

      for(int i = 0; i < temp.length; ++i) {
         result[i] = temp[i] - 48;
      }

      return result;
   }
}
