/* 
* Copyright 2016 Agencia Estatal de Administración Tibutaria
*
* Licencia con arreglo a la EUPL, Versión 1.1 o –en cuanto
* sean aprobadas por la Comisión Europea– versiones
* posteriores de la EUPL (la «Licencia»);
* Solo podrá usarse esta obra si se respeta la Licencia.
* Puede obtenerse una copia de la Licencia en:
*  
* https://joinup.ec.europa.eu/software/page/eupl
*  
* Salvo cuando lo exija la legislación aplicable o se acuerde
* por escrito, el programa distribuido con arreglo a la
* Licencia se distribuye «TAL CUAL», SIN GARANTÍAS NI CONDICIONES
* DE NINGÚN TIPO, ni expresasni implícitas.
*
* Véase la Licencia en el idioma concreto que rige los permisos y 
* limitaciones que establece la Licencia.
*/ 

package gestor.utiles;

import java.text.StringCharacterIterator;

public class ValidaNif {

   public ValidaNif() {
   }

   public boolean checkNif(String nifEntra) {
      if (nifEntra == null || nifEntra.length() == 0) {
         return false;
      }
       if (nifEntra.charAt(0) == '#') {
          return true;
      }
        Boolean r = ValExterna.ValFiscal.valIden(nifEntra);
        return r;
//      if (nifEntra.charAt(0) == 'Y') {
//         nifEntra = "1" + nifEntra.substring(1);
//      } else if (nifEntra.charAt(0) == 'Z') {
//         nifEntra = "2" + nifEntra.substring(1);
//      }
//      String elNif = aNif(nifEntra);
//      return (vNif(elNif) > 0);
   }

   public int vNif(String sNif) {
      nifOk = false;
      String dos = null;
      int multi = 0;
      int suma = 0;
      long cuent = 0L;
      long resto = 0L;
      sNif = sNif.trim();
      if (sNif.length() != 9) {
         return -2;
      }
      char Letra1 = '\0';
      char Letra2 = '\0';
      int NumeroLetras = 0;
      int PosLetra1 = 0;
      int PosLetra2 = 0;
      char datos[] = sNif.toCharArray();
      for (int i = 0; i < 9; i++) {
         char ch = datos[i];
         int tipo = Character.getType(ch);
         if (tipo == 1 && NumeroLetras == 0) {
            NumeroLetras++;
            Letra1 = ch;
            PosLetra1 = i;
            continue;
         }
         if (tipo == 1 && NumeroLetras == 1) {
            NumeroLetras++;
            Letra2 = ch;
            PosLetra2 = i;
            continue;
         }
         if (tipo == 1 && NumeroLetras == 2) {
            return -5;
         }
         if (tipo != 9) {
            return -4;
         }
      }

      if (NumeroLetras == 0) {
         if (datos[0] != '0') {
            return -20;
         }
         String sdos = sNif.substring(1);
         return !sdos.equals("11111111") && !sdos.equals("22222222") && !sdos.equals("33333333") && !sdos.equals("44444444") && !sdos.equals("55555555") && !sdos.equals("66666666") && !sdos.equals("77777777") && !sdos.equals("88888888") && !sdos.equals("99999999") && !sdos.equals("00000000") ? 0 : -21;
      }
      if (NumeroLetras == 1 && caracEnCad(LetrasCIF, datos[PosLetra1]) && PosLetra1 == 0 && Character.isDigit(datos[8])) {
         int i;
         for (i = 1; i < 8; i++) {
            if (i == 2 || i == 4 || i == 6) {
               suma += datos[i] - 48;
               continue;
            }
            multi = (datos[i] - 48) * 2;
            if (multi > 9) {
               multi -= 9;
            }
            suma += multi;
         }

         suma = 10 - suma % 10;
         if (suma == 10) {
            suma = 0;
         }
         if (suma == datos[i] - 48) {
            if (caracEnCad(LetrasCIFNORES, datos[PosLetra1])) {
               nifOk = true;
               return 23;
            } else {
               nifOk = true;
               return 20;
            }
         } else {
            return -10;
         }
      }
      if (NumeroLetras == 2 && (caracEnCad(LetrasCIF, datos[PosLetra1]) || caracEnCad(LetrasCIFORG, datos[PosLetra1])) && caracEnCad(Letras2CIF, datos[PosLetra2]) && PosLetra1 == 0 && PosLetra2 == 8) {
         for (int i = 1; i < 8; i++) {
            if (i == 2 || i == 4 || i == 6) {
               suma += datos[i] - 48;
               continue;
            }
            multi = (datos[i] - 48) * 2;
            if (multi > 9) {
               multi -= 9;
            }
            suma += multi;
         }

         suma = 10 - suma % 10;
         if (Letras2CIF[suma - 1] == datos[PosLetra2]) {
            nifOk = true;
            return !caracEnCad(LetrasCIF, datos[PosLetra1]) ? 22 : 21;
         } else {
            return -10;
         }
      }
      if (NumeroLetras == 1 && caracEnCad(Letras, datos[8]) && caracEnCad(LetrasNIF, datos[PosLetra1]) && PosLetra1 == 8) {
         StringBuffer buf = new StringBuffer(sNif.substring(0, PosLetra1));
         cuent = Long.parseLong(buf.toString());
         resto = cuent % 23L;
         if (resto + 1L > 23L) {
            return -12;
         }
         if (Letra1 == LetrasNIF[(int) resto]) {
            if (sNif.equals("00000001R") || sNif.equals("00000000T") || sNif.equals("99999999R")) {
               return -1;
            } else {
               nifOk = true;
               return 1;
            }
         } else {
            return -11;
         }
      }
      if (NumeroLetras == 2 && (datos[0] == 'K' || datos[0] == 'L' || datos[0] == 'M') && caracEnCad(LetrasNIF, datos[PosLetra2]) && PosLetra2 == 8) {
         dos = sNif.substring(1, 3);
         if (!caracEnCad(Numeros, dos.charAt(0)) || !caracEnCad(Numeros, dos.charAt(1))) {
            return -13;
         }
         int i = Integer.parseInt(dos);
         if (i < 1 || i > 56) {
            return -1;
         }
         dos = sNif.substring(1, PosLetra2);
         cuent = Long.parseLong(dos);
         resto = cuent % 23L;
         resto++;
         if (resto > 23L) {
            return -12;
         }
         if (Letra2 == LetrasNIF[(int) (resto - 1L)]) {
            nifOk = true;
            return 2;
         } else {
            return -11;
         }
      }
      if (NumeroLetras == 2 && datos[0] == 'X' && caracEnCad(LetrasNIF, datos[PosLetra2]) && PosLetra2 == 8) {
         dos = sNif.substring(1, PosLetra2);
         cuent = Long.parseLong(dos);
         resto = cuent % 23L;
         resto++;
         if (resto > 23L) {
            return -12;
         }
         if (Letra2 == LetrasNIF[(int) (resto - 1L)]) {
            nifOk = true;
            return 4;
         } else {
            return -11;
         }
      } else {
         return -1;
      }
   }

   public String aNif(String nif) {
      nif = quitaCaracRaros(nif);
      int tam = nif.length();
      if (tam > 9) {
         return "";
      }
      if (tam != 9) {
         StringBuffer inter = new StringBuffer(9);
         inter.append("000000000".substring(0, 9 - tam));
         inter.append(nif);
         nif = inter.toString();
      }
      return nif;
   }

   public static String quitaCaracRaros(String datos) {
      StringBuffer buf = new StringBuffer(datos.length());
      StringCharacterIterator iter = new StringCharacterIterator(datos);
      for (char c = iter.first(); c != '\uFFFF'; c = iter.next()) {
         if (Character.isLetterOrDigit(c)) {
            buf.append(c);
         }
      }

      return buf.toString();
   }

   public static boolean caracEnCad(char datos[], char ch) {
      boolean bRet = false;
      int tam = datos.length;
      int i = 0;
      do {
         if (i >= tam) {
            break;
         }
         if (datos[i] == ch) {
            bRet = true;
            break;
         }
         i++;
      } while (true);
      return bRet;
   }

   public static boolean caracEnCad(String datos, char ch) {
      boolean bRet = false;
      StringCharacterIterator iter = new StringCharacterIterator(datos);
      char c = iter.first();
      do {
         if (c == '\uFFFF') {
            break;
         }
         if (c == ch) {
            bRet = true;
            break;
         }
         c = iter.next();
      } while (true);
      return bRet;
   }

   public static boolean isAlfa(char ch) {
      String letras = "ABCDEFGHIJKLMN\321OPQRSTUVWXYZ\307,',-.\264 ";
      return letras.indexOf(ch) != -1;
   }

   public static boolean isAlfa(String cad) {
      cad = cad.toUpperCase();
      for (int i = 0; i < cad.length(); i++) {
         if (!isAlfa(cad.charAt(i))) {
            return false;
         }
      }

      return true;
   }
   boolean nifOk;
   public static final int TAM_NIF = 9;
   public static final int NIF_ERROR = -1;
   public static final int NIF_ERROR_TAMANO = -2;
   public static final int NIF_ERROR_BLANCOS = -3;
   public static final int NIF_ERROR_CARACTERES = -4;
   public static final int NIF_ERROR_3LETRAS = -5;
   public static final int NIF_ERROR_DATOSENTRADA = -6;
   public static final int CIF_ERROR_DC = -10;
   public static final int NIF_ERROR_DC = -11;
   public static final int NIF_ERROR_NUM = -12;
   public static final int NIF_ERROR_DOSNUM = -13;
   public static final int DNI_ERROR_MAX = -20;
   public static final int DNI_ERROR_VALOR = -21;
   public static final int DNI_OK = 0;
   public static final int NIF_OK = 1;
   public static final int NIF_NORESIDENTES = 2;
   public static final int NIF_MENORES14ANOS = 3;
   public static final int NIF_EXTRANJEROS = 4;
   public static final int CIF_OK = 20;
   public static final int CIF_EXTRANJERO_OK = 21;
   public static final int CIF_ORGANIZACION_OK = 22;
   public static final int CIF_NORESIDENTES_OK = 23;
   public static final char Numeros[] = {
      '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
   };
   public static final char Letras[] = {
      'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
      'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V',
      'W', 'X', 'Y', 'Z'
   };
   public static final char LetrasNIF[] = {
      'T', 'R', 'W', 'A', 'G', 'M', 'Y', 'F', 'P', 'D',
      'X', 'B', 'N', 'J', 'Z', 'S', 'Q', 'V', 'H', 'L',
      'C', 'K', 'E'
   };
   public static final char Letras2CIF[] = {
      'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'
   };
   public static final char LetrasCIF[] = {
      'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'U', 'V'
   };
   public static final char LetrasCIFORG[] = {
      'P', 'Q', 'S', 'N', 'R', 'W'
   };
   public static final char LetrasCIFNORES[] = {
      'E', 'G', 'H'
   };
   public static final String ceros = "000000000";
}
