package com.chenyang.nse.bussiness.tools.filesystem;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

public class JarUtilTool {
   public static void readJARList(String jarFilePath) throws IOException {
      JarFile jarFile = new JarFile(jarFilePath);
      Enumeration en = jarFile.entries();
      System.out.println("文件名\t文件大小\t压缩后的大小");

      while(en.hasMoreElements()) {
         process(en.nextElement());
      }

   }

   private static void process(Object obj) {
      JarEntry entry = (JarEntry)obj;
      String name = entry.getName();
      long size = entry.getSize();
      long compressedSize = entry.getCompressedSize();
      System.out.println(name + "\t" + size + "\t" + compressedSize);
   }

   public static void readJarFile(String jarFilePath, String fileName) throws IOException {
      JarFile jarFile = new JarFile(jarFilePath);
      JarEntry entry = jarFile.getJarEntry(fileName);
      InputStream input = jarFile.getInputStream(entry);
      readFile(input);
      jarFile.close();
   }

   public static void readFile(InputStream input) throws IOException {
      InputStreamReader in = new InputStreamReader(input);
      BufferedReader reader = new BufferedReader(in);

      String line;
      while((line = reader.readLine()) != null) {
         System.out.println(line);
      }

      reader.close();
   }

   public static byte[] readStream(InputStream inStream) throws Exception {
      ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
      byte[] buffer = new byte[1024];
      int len = -1;

      while((len = inStream.read(buffer)) != -1) {
         outSteam.write(buffer, 0, len);
      }

      outSteam.close();
      inStream.close();
      return outSteam.toByteArray();
   }

   public static void writeJarFile(String jarFilePath, String entryName, byte[] data) throws Exception {
      JarFile jarFile = new JarFile(jarFilePath);
      TreeMap tm = new TreeMap();
      Enumeration es = jarFile.entries();

      while(es.hasMoreElements()) {
         JarEntry je = (JarEntry)es.nextElement();
         byte[] b = readStream(jarFile.getInputStream(je));
         tm.put(je.getName(), b);
      }

      JarOutputStream jos = new JarOutputStream(new FileOutputStream(jarFilePath));
      Iterator it = tm.entrySet().iterator();

      boolean has;
      byte[] temp;
      for(has = false; it.hasNext(); jos.write(temp, 0, temp.length)) {
         Map.Entry item = (Map.Entry)it.next();
         String name = (String)item.getKey();
         JarEntry entry = new JarEntry(name);
         jos.putNextEntry(entry);
         if (name.equals(entryName)) {
            temp = data;
            has = true;
         } else {
            temp = (byte[])item.getValue();
         }
      }

      if (!has) {
         JarEntry newEntry = new JarEntry(entryName);
         jos.putNextEntry(newEntry);
         jos.write(data, 0, data.length);
      }

      jos.finish();
      jos.close();
   }

   public static void writeJarFileBatch(String jarFilePath, Map<String, byte[]> contents) throws Exception {
      JarFile jarFile = new JarFile(jarFilePath);
      TreeMap tm = new TreeMap();
      Enumeration es = jarFile.entries();

      while(es.hasMoreElements()) {
         JarEntry je = (JarEntry)es.nextElement();
         byte[] b = readStream(jarFile.getInputStream(je));
         tm.put(je.getName(), b);
      }

      JarOutputStream jos = new JarOutputStream(new FileOutputStream(jarFilePath));
      Iterator it = tm.entrySet().iterator();

      byte[] temp;
      for(boolean has = false; it.hasNext(); jos.write(temp, 0, temp.length)) {
         Map.Entry item = (Map.Entry)it.next();
         String name = (String)item.getKey();
         JarEntry entry = new JarEntry(name);
         jos.putNextEntry(entry);
         if (contents.containsKey(name)) {
            temp = (byte[])contents.get(name);
            contents.remove(name);
         } else {
            temp = (byte[])item.getValue();
         }
      }

      if (contents != null && contents.size() > 0) {
         contents.forEach((filename, data) -> {
            JarEntry newEntry = new JarEntry(filename);

            try {
               jos.putNextEntry(newEntry);
            } catch (IOException e) {
               e.printStackTrace();
            }

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

         });
      }

      jos.finish();
      jos.close();
   }

   public static void writeZipFileBatch(String zipFilePath, Map<String, byte[]> contents) throws Exception {
      ZipFile zipFile = new ZipFile(zipFilePath);
      TreeMap tm = new TreeMap();
      Enumeration es = zipFile.entries();

      while(es.hasMoreElements()) {
         ZipEntry je = (ZipEntry)es.nextElement();
         byte[] b = readStream(zipFile.getInputStream(je));
         tm.put(je.getName(), b);
      }

      ZipOutputStream jos = new ZipOutputStream(new FileOutputStream(zipFilePath));
      Iterator it = tm.entrySet().iterator();

      byte[] temp;
      for(boolean has = false; it.hasNext(); jos.write(temp, 0, temp.length)) {
         Map.Entry item = (Map.Entry)it.next();
         String name = (String)item.getKey();
         ZipEntry entry = new ZipEntry(name);
         jos.putNextEntry(entry);
         if (contents.containsKey(name)) {
            temp = (byte[])contents.get(name);
            contents.remove(name);
         } else {
            temp = (byte[])item.getValue();
         }
      }

      if (contents != null && contents.size() > 0) {
         contents.forEach((filename, data) -> {
            ZipEntry newEntry = new ZipEntry(filename);

            try {
               jos.putNextEntry(newEntry);
            } catch (IOException e) {
               e.getMessage();
            }

            try {
               jos.write(data, 0, data.length);
            } catch (IOException e) {
               e.getMessage();
            }

         });
      }

      jos.finish();
      jos.close();
   }

   public static void main(String[] args) throws Exception {
      readJarFile("D:\\esjavaclient-0.0.1-SNAPSHOT.jar", "es-info.properties");
      String data = "helloBabydsafsadfasdfsdafsdgasdgweqtqwegtqwfwefasdfasfadfasf";
      long start = System.currentTimeMillis();
      writeJarFile("D:\\esjavaclient-0.0.1-SNAPSHOT.jar", "es-info.properties", data.getBytes());
      long end = System.currentTimeMillis();
      System.out.println(end - start);
      readJarFile("D:\\esjavaclient-0.0.1-SNAPSHOT.jar", "es-info.properties");
   }
}
