package com.palacesun.masking.tools.sm4fpe;

import java.security.Security;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;
import java.util.regex.Pattern;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class SM4FPEIdentityNo extends SM4FPEBase {
   static ArrayList<SM4FPEEntity> identifyNoEntities = new ArrayList();
   static ArrayList identifyNoPrefix6;
   static char[] identifyNoCheck;
   static String[] identifyNoYearPrefix2;
   static ArrayList identifyNoMonthDay;
   static HashMap identifyNoPrefix6Map;
   static HashMap identifyNoCheckMap;
   static HashMap identifyNoYearPrefix2Map;
   static HashMap identifyNoMonthDayMap;
   private static Pattern identifyNoPattern;
   private static SimpleDateFormat identifyNoDateFormat;

   public String encryptEcb(String hexKey, String a) throws Exception {
      String out = this.encrypt(hexKey, a, identifyNoEntities);
      return out;
   }

   public String decryptEcb(String hexKey, String input) throws Exception {
      String out = this.decrypt(hexKey, input, identifyNoEntities);
      return out;
   }

   public int initTypes(String input, int m, SegmentType[] types, ArrayList<SM4FPEEntity> entities) throws Exception {
      int typeIndex = 0;
      if (input.length() == 18) {
         Integer index = (Integer)identifyNoPrefix6Map.get(input.substring(0, 6));
         typeIndex = this.setTypeIndex(types, typeIndex, index, 0, 6);
         index = (Integer)identifyNoYearPrefix2Map.get(input.substring(6, 8));
         typeIndex = this.setTypeIndex(types, typeIndex, index, 1, 2);
         index = (Integer)digitCharsMap.get(input.charAt(8));
         typeIndex = this.setTypeIndex(types, typeIndex, index, 2, 1);
         index = (Integer)digitCharsMap.get(input.charAt(9));
         typeIndex = this.setTypeIndex(types, typeIndex, index, 2, 1);
         index = (Integer)identifyNoMonthDayMap.get(input.substring(10, 14));
         typeIndex = this.setTypeIndex(types, typeIndex, index, 3, 4);
         index = (Integer)digitCharsMap.get(input.charAt(14));
         typeIndex = this.setTypeIndex(types, typeIndex, index, 2, 1);
         index = (Integer)digitCharsMap.get(input.charAt(15));
         typeIndex = this.setTypeIndex(types, typeIndex, index, 2, 1);
         index = (Integer)digitCharsMap.get(input.charAt(16));
         typeIndex = this.setTypeIndex(types, typeIndex, index, 2, 1);
         index = (Integer)identifyNoCheckMap.get(input.charAt(17));
         typeIndex = this.setTypeIndex(types, typeIndex, index, 4, 1);
      } else if (input.length() == 15) {
         Integer index = (Integer)identifyNoPrefix6Map.get(input.substring(0, 6));
         typeIndex = this.setTypeIndex(types, typeIndex, index, 0, 6);
         index = (Integer)digitCharsMap.get(input.charAt(6));
         typeIndex = this.setTypeIndex(types, typeIndex, index, 2, 1);
         index = (Integer)digitCharsMap.get(input.charAt(7));
         typeIndex = this.setTypeIndex(types, typeIndex, index, 2, 1);
         index = (Integer)identifyNoMonthDayMap.get(input.substring(8, 12));
         typeIndex = this.setTypeIndex(types, typeIndex, index, 3, 4);
         index = (Integer)digitCharsMap.get(input.charAt(12));
         typeIndex = this.setTypeIndex(types, typeIndex, index, 2, 1);
         index = (Integer)digitCharsMap.get(input.charAt(13));
         typeIndex = this.setTypeIndex(types, typeIndex, index, 2, 1);
         index = (Integer)digitCharsMap.get(input.charAt(14));
         typeIndex = this.setTypeIndex(types, typeIndex, index, 2, 1);
      } else {
         for(int i = 0; i < input.length(); ++i) {
            Integer index = (Integer)digitCharsMap.get(input.charAt(i));
            typeIndex = this.setTypeIndex(types, typeIndex, index, 2, 1);
         }
      }

      return typeIndex++;
   }

   private int setTypeIndex(SegmentType[] types, int typeIndex, Integer index, int type, int length) {
      if (index != null) {
         types[typeIndex].type = type;
      } else {
         types[typeIndex].type = 99999;
      }

      types[typeIndex].length = length;
      ++typeIndex;
      return typeIndex;
   }

   String generateInputRandom(String input) {
      Random random = new Random();
      if (random.nextBoolean()) {
         input = input + ((SM4FPEEntity)identifyNoEntities.get(0)).getList().get(random.nextInt(((SM4FPEEntity)identifyNoEntities.get(0)).getList().size()));
         input = input + ((SM4FPEEntity)identifyNoEntities.get(1)).getList().get(random.nextInt(((SM4FPEEntity)identifyNoEntities.get(1)).getList().size()));
         input = input + ((SM4FPEEntity)identifyNoEntities.get(2)).getList().get(random.nextInt(((SM4FPEEntity)identifyNoEntities.get(2)).getList().size()));
         input = input + ((SM4FPEEntity)identifyNoEntities.get(2)).getList().get(random.nextInt(((SM4FPEEntity)identifyNoEntities.get(2)).getList().size()));
         input = input + ((SM4FPEEntity)identifyNoEntities.get(3)).getList().get(random.nextInt(((SM4FPEEntity)identifyNoEntities.get(3)).getList().size()));
         input = input + ((SM4FPEEntity)identifyNoEntities.get(2)).getList().get(random.nextInt(((SM4FPEEntity)identifyNoEntities.get(2)).getList().size()));
         input = input + ((SM4FPEEntity)identifyNoEntities.get(2)).getList().get(random.nextInt(((SM4FPEEntity)identifyNoEntities.get(2)).getList().size()));
         input = input + ((SM4FPEEntity)identifyNoEntities.get(2)).getList().get(random.nextInt(((SM4FPEEntity)identifyNoEntities.get(2)).getList().size()));
         input = input + ((SM4FPEEntity)identifyNoEntities.get(4)).getList().get(random.nextInt(((SM4FPEEntity)identifyNoEntities.get(4)).getList().size()));
      } else {
         input = input + ((SM4FPEEntity)identifyNoEntities.get(0)).getList().get(random.nextInt(((SM4FPEEntity)identifyNoEntities.get(0)).getList().size()));
         input = input + ((SM4FPEEntity)identifyNoEntities.get(2)).getList().get(random.nextInt(((SM4FPEEntity)identifyNoEntities.get(2)).getList().size()));
         input = input + ((SM4FPEEntity)identifyNoEntities.get(2)).getList().get(random.nextInt(((SM4FPEEntity)identifyNoEntities.get(2)).getList().size()));
         input = input + ((SM4FPEEntity)identifyNoEntities.get(3)).getList().get(random.nextInt(((SM4FPEEntity)identifyNoEntities.get(3)).getList().size()));
         input = input + ((SM4FPEEntity)identifyNoEntities.get(2)).getList().get(random.nextInt(((SM4FPEEntity)identifyNoEntities.get(2)).getList().size()));
         input = input + ((SM4FPEEntity)identifyNoEntities.get(2)).getList().get(random.nextInt(((SM4FPEEntity)identifyNoEntities.get(2)).getList().size()));
         input = input + ((SM4FPEEntity)identifyNoEntities.get(2)).getList().get(random.nextInt(((SM4FPEEntity)identifyNoEntities.get(2)).getList().size()));
      }

      return input;
   }

   public static boolean isIdentifyNo(String idno) {
      boolean result = false;
      if (idno == null) {
         System.out.println("dd");
      }

      idno = idno.trim();
      if (idno.length() == 18) {
         idno = idno.toUpperCase();
         if (null == identifyNoPattern) {
            identifyNoPattern = Pattern.compile("[0-9]{17}[0-9X]");
         }

         if (identifyNoPattern.matcher(idno).matches() && checkIdentifyNoFirstSix(idno) && checkIdentifyNoDate(idno.substring(6, 14))) {
            result = true;
         }
      } else if (idno.length() == 15) {
         Pattern identifyNoPattern15 = Pattern.compile("[0-9]{15}");
         if (identifyNoPattern15.matcher(idno).matches() && checkIdentifyNoFirstSix(idno) && checkIdentifyNoDate("19" + idno.substring(6, 12))) {
            result = true;
         }
      }

      return result;
   }

   public static boolean checkIdentifyNoFirstSix(String idno) {
      boolean result = false;
      if (identifyNoPrefix6Map.get(idno.substring(0, 6)) != null) {
         result = true;
      }

      return result;
   }

   public static boolean checkIdentifyNoDate(String datestr) {
      boolean result = false;
      if (null == identifyNoDateFormat) {
         identifyNoDateFormat = new SimpleDateFormat("yyyyMMdd");
         identifyNoDateFormat.setLenient(true);
      }

      try {
         identifyNoDateFormat.parse(datestr);
         int year = Integer.parseInt(datestr.substring(0, 4));
         if (year >= 1800) {
            result = true;
         }
      } catch (ParseException e) {
         System.out.println(e.getMessage());
      }

      return result;
   }

   public static boolean check(String input) {
      return isIdentifyNo(input);
   }

   public static ArrayList<SM4FPEEntity> getSm4FPEEntities() {
      return identifyNoEntities;
   }

   static {
      Security.addProvider(new BouncyCastleProvider());
      identifyNoPrefix6 = readFileList("identifyno_prefix6.txt", "UTF-8");
      identifyNoCheck = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'X', 'x'};
      identifyNoYearPrefix2 = new String[]{"18", "19", "20"};
      identifyNoMonthDay = readFileList("monthday.txt", "UTF-8");
      identifyNoPrefix6Map = new HashMap();

      for(int i = 0; i < identifyNoPrefix6.size(); ++i) {
         identifyNoPrefix6Map.put(identifyNoPrefix6.get(i), i);
      }

      identifyNoCheckMap = new HashMap();

      for(int i = 0; i < identifyNoCheck.length; ++i) {
         identifyNoCheckMap.put(identifyNoCheck[i], i);
      }

      identifyNoYearPrefix2Map = new HashMap();

      for(int i = 0; i < identifyNoYearPrefix2.length; ++i) {
         identifyNoYearPrefix2Map.put(identifyNoYearPrefix2[i], i);
      }

      identifyNoMonthDayMap = new HashMap();

      for(int i = 0; i < identifyNoMonthDay.size(); ++i) {
         identifyNoMonthDayMap.put(identifyNoMonthDay.get(i), i);
      }

      try {
         identifyNoEntities.add(new SM4FPEEntity(0, identifyNoPrefix6, identifyNoPrefix6Map));
         identifyNoEntities.add(new SM4FPEEntity(1, toArrayList(identifyNoYearPrefix2), identifyNoYearPrefix2Map));
         identifyNoEntities.add(new SM4FPEEntity(2, toArrayList(digitChars), digitCharsMap));
         identifyNoEntities.add(new SM4FPEEntity(3, identifyNoMonthDay, identifyNoMonthDayMap));
         identifyNoEntities.add(new SM4FPEEntity(4, toArrayList(identifyNoCheck), identifyNoCheckMap));
      } catch (RuntimeException e) {
         throw e;
      }
   }
}
