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

import com.chenyang.nse.bussiness.config.PropertiesLoaderUtils;
import java.io.IOException;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Properties;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
import org.bouncycastle.util.encoders.Hex;

public class AesEncryptUtils {
   private static final String ALGORITHMSTR = "AES/ECB/PKCS5Padding";
   private static final String ENCRYPT_ALGO = "AES/GCM/NoPadding";
   private static final String ALGORITHM_NAME = "AES";
   public static final int DEF_KEY_SIZE = 128;
   public static final int DEF_KEY_SIZE_256 = 256;
   public static final int DEF_KEY_SIZE_192 = 192;
   public static final byte[] IV = new byte[]{-80, 104, -85, -96, -31, -90, 1, 120, 35, 121, 26, 41};
   private static final String ENCODING = "UTF-8";
   private static Properties properties;
   private static String ENCRYPT_LIKE_SPLIT;
   private static final String ENCRYPT_LIKE_OPEN = "1";

   public static String encrypt_ecb(String encryptKey, String paramStr, String isLike, String keepfirst, String encdigit, String twoindex) throws Exception {
      KeyGenerator kgen = KeyGenerator.getInstance("AES");
      kgen.init(128);
      Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
      byte[] keyData = ByteUtils.fromHexString(encryptKey);
      cipher.init(1, new SecretKeySpec(keyData, "AES"));
      String prefix = null;
      String enc = paramStr;
      String suffix = null;
      if (!StringUtils.isBlank(keepfirst)) {
         if (!"0".equals(keepfirst) && !"1".equals(keepfirst)) {
            if (!"2".equals(keepfirst)) {
               return paramStr;
            }

            int first = 0;
            if (StringUtils.isNotBlank(encdigit)) {
               first = Integer.parseInt(encdigit);
            }

            int last = 0;
            if (StringUtils.isNotBlank(twoindex)) {
               last = Integer.parseInt(twoindex);
            }

            if (first + last >= paramStr.length() || first >= paramStr.length() || last >= paramStr.length()) {
               return paramStr;
            }

            prefix = paramStr.substring(0, first);
            enc = paramStr.substring(first, paramStr.length() - last);
            suffix = paramStr.substring(paramStr.length() - last);
         } else if (StringUtils.isNotBlank(encdigit)) {
            if (Integer.parseInt(encdigit) >= paramStr.length()) {
               return paramStr;
            }

            if (Integer.parseInt(encdigit) != 0) {
               if ("0".equals(keepfirst)) {
                  prefix = paramStr.substring(0, Integer.parseInt(encdigit));
                  enc = paramStr.substring(Integer.parseInt(encdigit));
               } else if ("1".equals(keepfirst)) {
                  enc = paramStr.substring(0, paramStr.length() - Integer.parseInt(encdigit));
                  suffix = paramStr.substring(paramStr.length() - Integer.parseInt(encdigit));
               }
            }
         }
      }

      String encResult;
      if ("1".equals(isLike)) {
         StringBuilder sb = new StringBuilder();

         for(int i = 0; i < enc.length(); ++i) {
            char c = enc.charAt(i);
            byte[] srcData = (c + "").getBytes("UTF-8");
            byte[] b = cipher.doFinal(srcData);
            String s = Base64.encodeBase64String(b);
            sb.append(s).append(ENCRYPT_LIKE_SPLIT);
         }

         encResult = sb.deleteCharAt(sb.length() - 1).toString();
      } else {
         byte[] b = cipher.doFinal(enc.getBytes("UTF-8"));
         encResult = Base64.encodeBase64String(b);
      }

      if ("0".equals(keepfirst) && null != prefix) {
         encResult = prefix + encResult;
      } else if ("1".equals(keepfirst) && null != suffix) {
         encResult = encResult + suffix;
      } else if ("2".equals(keepfirst)) {
         if (null != prefix) {
            encResult = prefix + encResult;
         }

         if (null != suffix) {
            encResult = encResult + suffix;
         }
      }

      return encResult;
   }

   public static String encrypt(String encryptKey, String paramStr, String isLike, String keepfirst, String encdigit, String twoindex) throws Exception {
      byte[] keyBytes = Hex.decode(encryptKey);
      String prefix = null;
      String enc = paramStr;
      String suffix = null;
      if (!StringUtils.isBlank(keepfirst)) {
         if (!"0".equals(keepfirst) && !"1".equals(keepfirst)) {
            if (!"2".equals(keepfirst)) {
               return paramStr;
            }

            int first = 0;
            if (StringUtils.isNotBlank(encdigit)) {
               first = Integer.parseInt(encdigit);
            }

            int last = 0;
            if (StringUtils.isNotBlank(twoindex)) {
               last = Integer.parseInt(twoindex);
            }

            if (first + last >= paramStr.length() || first >= paramStr.length() || last >= paramStr.length()) {
               return paramStr;
            }

            prefix = paramStr.substring(0, first);
            enc = paramStr.substring(first, paramStr.length() - last);
            suffix = paramStr.substring(paramStr.length() - last);
         } else if (StringUtils.isNotBlank(encdigit)) {
            if (Integer.parseInt(encdigit) >= paramStr.length()) {
               return paramStr;
            }

            if (Integer.parseInt(encdigit) != 0) {
               if ("0".equals(keepfirst)) {
                  prefix = paramStr.substring(0, Integer.parseInt(encdigit));
                  enc = paramStr.substring(Integer.parseInt(encdigit));
               } else if ("1".equals(keepfirst)) {
                  enc = paramStr.substring(0, paramStr.length() - Integer.parseInt(encdigit));
                  suffix = paramStr.substring(paramStr.length() - Integer.parseInt(encdigit));
               }
            }
         }
      }

      String encResult;
      if ("1".equals(isLike)) {
         StringBuilder sb = new StringBuilder();

         for(int i = 0; i < enc.length(); ++i) {
            char c = enc.charAt(i);
            byte[] srcData = (c + "").getBytes("UTF-8");
            SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
            Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
            cipher.init(1, keySpec, new GCMParameterSpec(128, IV));
            byte[] ciphertext = cipher.doFinal(srcData);
            String s = Hex.toHexString(ciphertext);
            sb.append(s).append(ENCRYPT_LIKE_SPLIT);
         }

         encResult = sb.deleteCharAt(sb.length() - 1).toString();
      } else {
         byte[] srcData = enc.getBytes("UTF-8");
         SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
         Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
         cipher.init(1, keySpec, new GCMParameterSpec(128, IV));
         byte[] ciphertext = cipher.doFinal(srcData);
         encResult = Hex.toHexString(ciphertext);
      }

      if ("0".equals(keepfirst) && null != prefix) {
         encResult = prefix + encResult;
      } else if ("1".equals(keepfirst) && null != suffix) {
         encResult = encResult + suffix;
      } else if ("2".equals(keepfirst)) {
         if (null != prefix) {
            encResult = prefix + encResult;
         }

         if (null != suffix) {
            encResult = encResult + suffix;
         }
      }

      return encResult;
   }

   public static String decrypt_ecb(String decryptKey, String paramStr, String isLike, String keepfirst, String encdigit, String twoindex) throws Exception {
      KeyGenerator kgen = KeyGenerator.getInstance("AES");
      kgen.init(128);
      Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
      byte[] keyData = ByteUtils.fromHexString(decryptKey);
      cipher.init(2, new SecretKeySpec(keyData, "AES"));
      String prefix = null;
      String enc = paramStr;
      String suffix = null;
      if (!StringUtils.isBlank(keepfirst)) {
         if (!"0".equals(keepfirst) && !"1".equals(keepfirst)) {
            if ("2".equals(keepfirst)) {
               int first = 0;
               if (StringUtils.isNotBlank(encdigit)) {
                  first = Integer.parseInt(encdigit);
               }

               int last = 0;
               if (StringUtils.isNotBlank(twoindex)) {
                  last = Integer.parseInt(twoindex);
               }

               if (first + last >= paramStr.length() || first >= paramStr.length() || last >= paramStr.length()) {
                  return paramStr;
               }

               prefix = paramStr.substring(0, first);
               enc = paramStr.substring(first, paramStr.length() - last);
               suffix = paramStr.substring(paramStr.length() - last);
            }
         } else if (StringUtils.isNotBlank(encdigit)) {
            if (Integer.parseInt(encdigit) >= paramStr.length()) {
               return paramStr;
            }

            if (Integer.parseInt(encdigit) != 0) {
               if ("0".equals(keepfirst)) {
                  prefix = paramStr.substring(0, Integer.parseInt(encdigit));
                  enc = paramStr.substring(Integer.parseInt(encdigit));
               } else if ("1".equals(keepfirst)) {
                  enc = paramStr.substring(0, paramStr.length() - Integer.parseInt(encdigit));
                  suffix = paramStr.substring(paramStr.length() - Integer.parseInt(encdigit));
               }
            }
         }
      }

      String encResult;
      if ("1".equals(isLike)) {
         StringBuilder sb = new StringBuilder();
         String[] split = enc.split(ENCRYPT_LIKE_SPLIT);

         for(String s : split) {
            try {
               byte[] encryptBytes = Base64.decodeBase64(s);
               byte[] decryptBytes = cipher.doFinal(encryptBytes);
               sb.append(new String(decryptBytes));
            } catch (Exception e) {
               e.printStackTrace();
            }
         }

         encResult = sb.toString();
      } else {
         byte[] encryptBytes = Base64.decodeBase64(enc);
         byte[] decryptBytes = cipher.doFinal(encryptBytes);
         encResult = new String(decryptBytes);
      }

      if ("0".equals(keepfirst) && null != prefix) {
         encResult = prefix + encResult;
      } else if ("1".equals(keepfirst) && null != suffix) {
         encResult = encResult + suffix;
      } else if ("2".equals(keepfirst)) {
         if (null != prefix) {
            encResult = prefix + encResult;
         }

         if (null != suffix) {
            encResult = encResult + suffix;
         }
      }

      return encResult;
   }

   public static String decrypt(String decryptKey, String paramStr, String isLike, String keepfirst, String encdigit, String twoindex) throws Exception {
      byte[] keyBytes = Hex.decode(decryptKey);
      String prefix = null;
      String enc = paramStr;
      String suffix = null;
      if (!StringUtils.isBlank(keepfirst)) {
         if (!"0".equals(keepfirst) && !"1".equals(keepfirst)) {
            if ("2".equals(keepfirst)) {
               int first = 0;
               if (StringUtils.isNotBlank(encdigit)) {
                  first = Integer.parseInt(encdigit);
               }

               int last = 0;
               if (StringUtils.isNotBlank(twoindex)) {
                  last = Integer.parseInt(twoindex);
               }

               if (first + last >= paramStr.length() || first >= paramStr.length() || last >= paramStr.length()) {
                  return paramStr;
               }

               prefix = paramStr.substring(0, first);
               enc = paramStr.substring(first, paramStr.length() - last);
               suffix = paramStr.substring(paramStr.length() - last);
            }
         } else if (StringUtils.isNotBlank(encdigit)) {
            if (Integer.parseInt(encdigit) >= paramStr.length()) {
               return paramStr;
            }

            if (Integer.parseInt(encdigit) != 0) {
               if ("0".equals(keepfirst)) {
                  prefix = paramStr.substring(0, Integer.parseInt(encdigit));
                  enc = paramStr.substring(Integer.parseInt(encdigit));
               } else if ("1".equals(keepfirst)) {
                  enc = paramStr.substring(0, paramStr.length() - Integer.parseInt(encdigit));
                  suffix = paramStr.substring(paramStr.length() - Integer.parseInt(encdigit));
               }
            }
         }
      }

      String encResult;
      if ("1".equals(isLike)) {
         StringBuilder sb = new StringBuilder();
         String[] split = enc.split(ENCRYPT_LIKE_SPLIT);

         for(String s : split) {
            try {
               byte[] encryptBytes = Hex.decode(s);
               SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
               Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
               cipher.init(2, keySpec, new GCMParameterSpec(128, IV));
               byte[] decryptedData = cipher.doFinal(encryptBytes);
               sb.append(new String(decryptedData, "UTF-8"));
            } catch (Exception e) {
               e.printStackTrace();
            }
         }

         encResult = sb.toString();
      } else {
         byte[] encryptBytes = Hex.decode(enc);
         SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
         Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
         cipher.init(2, keySpec, new GCMParameterSpec(128, IV));
         byte[] decryptedData = cipher.doFinal(encryptBytes);
         encResult = new String(decryptedData, "UTF-8");
      }

      if ("0".equals(keepfirst) && null != prefix) {
         encResult = prefix + encResult;
      } else if ("1".equals(keepfirst) && null != suffix) {
         encResult = encResult + suffix;
      } else if ("2".equals(keepfirst)) {
         if (null != prefix) {
            encResult = prefix + encResult;
         }

         if (null != suffix) {
            encResult = encResult + suffix;
         }
      }

      return encResult;
   }

   public static String generaKey() throws Exception {
      return Hex.toHexString(generaKey(128));
   }

   public static String generaKeyTwo() throws Exception {
      return Hex.toHexString(generaKey(256));
   }

   public static String generaKeyThree() throws Exception {
      return Hex.toHexString(generaKey(192));
   }

   public static byte[] generaKey(int keySize) throws Exception {
      KeyGenerator kg = KeyGenerator.getInstance("AES");
      kg.init(keySize, new SecureRandom());
      return kg.generateKey().getEncoded();
   }

   public static void main(String[] args) throws Exception {
      String key = generaKeyThree();
      System.out.println(key);
      String data = "111_aaaaaaaaaaaaa";
      System.out.println(data);
      String encrypt = encrypt(key, data, "1", "0", "3", (String)null);
      System.out.println(encrypt);
      String decrypt = decrypt(key, encrypt, "1", "0", "3", (String)null);
      System.out.println(decrypt);
      System.out.println(data.equals(decrypt));
   }

   static {
      try {
         properties = PropertiesLoaderUtils.loadAllProperties("config.properties");
         ENCRYPT_LIKE_SPLIT = properties.get("encryption.like.split").toString();
      } catch (IOException e) {
         e.printStackTrace();
      }

      Security.addProvider(new BouncyCastleProvider());
   }
}
