package com.palacesun.masking.tools;

import com.palacesun.engine.gateway.EncryptionGatewayManager;
import com.palacesun.masking.adapter.StringUtils;
import com.palacesun.masking.vo.Columninfo;
import java.security.SecureRandom;
import java.util.Properties;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

public class DESUtil {
   private static final String ENCODING = "UTF-8";
   public static final String ALGORITHM_NAME = "DES";
   public static final int DEFAULT_KEY_SIZE = 56;
   private static Properties properties;
   private static String ENCRYPT_LIKE_SPLIT = EncryptionGatewayManager.getParameterValue("encryption.like.split");
   private static final String ENCRYPT_LIKE_OPEN = "1";

   public static String generateKey() throws Exception {
      return byteToHexString(generateKey(56));
   }

   private static String byteToHexString(byte[] bytes) {
      StringBuffer sb = new StringBuffer(bytes.length);

      for(int i = 0; i < bytes.length; ++i) {
         String sTemp = Integer.toHexString(255 & bytes[i]);
         if (sTemp.length() < 2) {
            sb.append(0);
         }

         sb.append(sTemp.toUpperCase());
      }

      return sb.toString();
   }

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

   public static String encryptEcb(String hexKey, String paramStr, String isLike, String keepfirst, String encdigit, String twoindex, String... encryptMode) throws Throwable {
      try {
         byte[] keyData = hexStringToByteArray(hexKey);
         DESKeySpec desKey = new DESKeySpec(keyData);
         SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
         SecretKey secretKey = keyFactory.generateSecret(desKey);
         Cipher cipher = Cipher.getInstance("DES");
         cipher.init(1, secretKey, new SecureRandom());
         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 = byteToHexString(b);
               sb.append(s).append(ENCRYPT_LIKE_SPLIT);
            }

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

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

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

            return encResult;
         }
      } catch (Throwable e) {
         throw e;
      }
   }

   public static String decryptEcb(String hexKey, String paramStr, String isLike, String keepfirst, String encdigit, String twoindex, String... encryptMode) throws Throwable {
      try {
         byte[] keyData = hexStringToByteArray(hexKey);
         DESKeySpec desKey = new DESKeySpec(keyData);
         SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
         SecretKey secretkey = keyFactory.generateSecret(desKey);
         Cipher cipher = Cipher.getInstance("DES");
         cipher.init(2, secretkey, new SecureRandom());
         String prefix = null;
         String enc = paramStr;
         String suffix = null;
         if (!StringUtils.isBlank(encdigit)) {
            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)) {
                     suffix = paramStr.substring(paramStr.length() - Integer.parseInt(encdigit));
                     enc = paramStr.substring(0, 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[] cipherData = hexStringToByteArray(s);
                  byte[] decryptBytes = cipher.doFinal(cipherData);
                  sb.append(new String(decryptBytes, "UTF-8"));
               } catch (Exception e) {
                  e.printStackTrace();
               }
            }

            encResult = sb.toString();
         } else {
            byte[] cipherData = hexStringToByteArray(enc);
            encResult = new String(cipher.doFinal(cipherData), "UTF-8");
         }

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

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

            return encResult;
         }
      } catch (Throwable e) {
         throw e;
      }
   }

   private static byte[] hexStringToByteArray(String s) {
      int len = s.length();
      byte[] data = new byte[len / 2];

      for(int i = 0; i < len; i += 2) {
         data[i / 2] = (byte)((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16));
      }

      return data;
   }

   public static void main(String[] args) throws Throwable {
      String key = generateKey();
      System.out.println(key);
      String data = "~这是yuanshi的明文xinxi在这里呢,1。";
      System.out.println(data);
      String encrypt = encryptEcb(key, data, "1", "0", "3", "0");
      System.out.println(encrypt);
      String decrypt = decryptEcb(key, encrypt, "1", "0", "3", "0");
      System.out.println(decrypt);
      System.out.println(data.equals(decrypt));
      encrypt = ReflectUtil.engine("DES", data, key, "1", "0", "3", "0", true, (Columninfo)null);
      System.out.println(encrypt);
      decrypt = ReflectUtil.engine("DES", encrypt, key, "1", "0", "3", "0", false, (Columninfo)null);
      System.out.println(decrypt);
      System.out.println(data.equals(decrypt));
   }
}
