package utils;

import java.math.BigInteger;

import org.apache.commons.lang.StringUtils;

public class Formalismi {

	
	public static final int IBANNUMBER_MIN_SIZE = 15;
    public static final int IBANNUMBER_MAX_SIZE = 34;
    public static final BigInteger IBANNUMBER_MAGIC_NUMBER = new BigInteger("97");

	/// <summary>
	/// Get for the input String ONLY chars in pattern
	/// </summary>
	/// <param name="str">String to parse</param>
	/// <param name="pat">Pattern</param>
	/// <returns></returns>
	public static String ONLY( String str, String pat )
	{
		String newStr = "";
		int found;

		for( int t=0; t!=str.length(); t++ ) 
		{
			found = pat.indexOf( str.charAt(t) );
			if( found != -1 ) 
				newStr += pat.charAt(found);
		}

		return newStr;
	}

	/// <summary>
	/// Get fot the input String ONLY numeric chars
	/// </summary>
	/// <param name="str">String to parse</param>
	/// <returns></returns>
	public static String ONLYNumbers( String str )
	{
		if (str == null || "".equals(str)) 
			return "";
		//if( str == String.Empty ) return "0";
		return ONLY(str, "0123456789");
	}

	public static boolean IsAlpha(String valore)
	{
		if( valore == null || "".equals(valore) ) 
			return true;
		return ONLY( valore, "ABCDEFGHJKLMNPQRSTUVWXYZ").length() == valore.length();
	}

	public static boolean IsNumeric(String valore)
	{
		if( valore == null || "".equals(valore) ) return true;
		return ONLYNumbers( valore ).length() == valore.length();
	}
	
	/// <summary>
	/// Get the last (right) "len" chars of the String
	/// </summary>
	/// <param name="str">String to evaluate</param>
	/// <param name="len">Length of result String</param>
	/// <returns></returns>
	public static String Right( String str, int len )
	{
		int l = str.length();

		if( l < len )
			return str;
		else
			return str.substring( l-len );
	}

	public static boolean ContaintsCBIInvalidsValues( String v )
	{
		if( v == null ) return false;

		for(int i=0;i<v.length();i++)
		{
			char c =v.charAt(i);
			if( !(c == ' ' ||
				c == '"' ||
				//(c >= 0x24 && c <= 0x2E) ||
				(c >= 0x30 && c <= 0x39) ||
				(c >= 0x41 && c <= 0x5A) ||
				c == '_' || c == '.' || c == '/' || c == '&' ||
				(c >= 0x61 && c <= 0x7A)) ) return true;
		}
		return false;
	}


	public static boolean CheckCin(String inCin, String inAbi, String inCab, String inConto)
	{
		String Coordinate = (StringUtils.leftPad(inAbi,5,'0') +
												StringUtils.leftPad(inCab,5,'0') +
												StringUtils.leftPad(inConto,12,'0').substring(0,12)).toUpperCase();
		int SommaCaratteri = 0;

		for( int i=0; i!=22; i++ ) 
		{
			boolean Pari = false;

			if( (i+1) % 2 == 0 ) Pari = true;

			if( Coordinate.substring(i,i+1).equals("A") ||Coordinate.substring(i,i+1).equals("0")) 
					SommaCaratteri += (Pari == true) ? 0 : 1;
			else if( Coordinate.substring(i,i+1).equals("B") ||Coordinate.substring(i,i+1).equals("1"))
					SommaCaratteri += (Pari == true) ? 1 : 0;
			else if( Coordinate.substring(i,i+1).equals("C") ||Coordinate.substring(i,i+1).equals("2"))
					SommaCaratteri += (Pari == true) ? 2 : 5;
			else if( Coordinate.substring(i,i+1).equals("D") ||Coordinate.substring(i,i+1).equals("3"))
					SommaCaratteri += (Pari == true) ? 3 : 7;
			else if( Coordinate.substring(i,i+1).equals("E") ||Coordinate.substring(i,i+1).equals("4"))
					SommaCaratteri += (Pari == true) ? 4 : 9;
			else if( Coordinate.substring(i,i+1).equals("F") ||Coordinate.substring(i,i+1).equals("5"))
					SommaCaratteri += (Pari == true) ? 5 : 13;
			else if( Coordinate.substring(i,i+1).equals("G") ||Coordinate.substring(i,i+1).equals("6"))
					SommaCaratteri += (Pari == true) ? 6 : 15;
			else if( Coordinate.substring(i,i+1).equals("H") ||Coordinate.substring(i,i+1).equals("7"))
							SommaCaratteri += (Pari == true) ? 7 : 17;
			else if( Coordinate.substring(i,i+1).equals("I") ||Coordinate.substring(i,i+1).equals("8"))
					SommaCaratteri += (Pari == true) ? 8 : 19;
			else if( Coordinate.substring(i,i+1).equals("J") ||Coordinate.substring(i,i+1).equals("9"))
					SommaCaratteri += (Pari == true) ? 9 : 21;
			else if( Coordinate.substring(i,i+1).equals("K"))
					SommaCaratteri += (Pari == true) ? 10 : 2;
			else if( Coordinate.substring(i,i+1).equals("L"))
					SommaCaratteri += (Pari == true) ? 11 : 4;
			else if( Coordinate.substring(i,i+1).equals("M"))
				SommaCaratteri += (Pari == true) ? 12 : 18;
			else if( Coordinate.substring(i,i+1).equals("N"))
				SommaCaratteri += (Pari == true) ? 13 : 20;
			else if( Coordinate.substring(i,i+1).equals("O"))
				SommaCaratteri += (Pari == true) ? 14 : 11;
			else if( Coordinate.substring(i,i+1).equals("P"))
					SommaCaratteri += (Pari == true) ? 15 : 3;
			else if( Coordinate.substring(i,i+1).equals("Q"))
					SommaCaratteri += (Pari == true) ? 16 : 6;
			else if( Coordinate.substring(i,i+1).equals("R"))
					SommaCaratteri += (Pari == true) ? 17 : 8;
			else if( Coordinate.substring(i,i+1).equals("S"))
					SommaCaratteri += (Pari == true) ? 18 : 12;
			else if( Coordinate.substring(i,i+1).equals("T"))
					SommaCaratteri += (Pari == true) ? 19 : 14;
			else if( Coordinate.substring(i,i+1).equals("U"))
					SommaCaratteri += (Pari == true) ? 20 : 16;
			else if( Coordinate.substring(i,i+1).equals("V"))
					SommaCaratteri += (Pari == true) ? 21 : 10;
			else if( Coordinate.substring(i,i+1).equals("W"))
					SommaCaratteri += 22;
			else if( Coordinate.substring(i,i+1).equals("X"))
					SommaCaratteri += (Pari == true) ? 23 : 25;
			else if( Coordinate.substring(i,i+1).equals("Y"))
					SommaCaratteri += 24;
			else if( Coordinate.substring(i,i+1).equals("Z"))
					SommaCaratteri += (Pari == true) ? 25 : 23;
			else if( Coordinate.substring(i,i+1).equals("-"))
					SommaCaratteri += (Pari == true) ? 26 : 27;
			else if( Coordinate.substring(i,i+1).equals("."))
					SommaCaratteri += (Pari == true) ? 27 : 28;
			else if( Coordinate.substring(i,i+1).equals(" "))
					SommaCaratteri += (Pari == true) ? 28 : 26;
			
		}

		switch( SommaCaratteri % 26 ) 
		{
			case 0:
				return inCin.equals("A");
			case 1:
				return inCin.equals("B");
			case 2:
				return inCin.equals("C");
			case 3:
				return inCin.equals("D");
			case 4:
				return inCin.equals("E");
			case 5:
				return inCin.equals("F");
			case 6:
				return inCin.equals("G");
			case 7:
				return inCin.equals("H");
			case 8:
				return inCin.equals("I");
			case 9:
				return inCin.equals("J");
			case 10:
				return inCin.equals("K");
			case 11:
				return inCin.equals("L");
			case 12:
				return inCin.equals("M");
			case 13:
				return inCin.equals("N");
			case 14:
				return inCin.equals("O");
			case 15:
				return inCin.equals("P");
			case 16:
				return inCin.equals("Q");
			case 17:
				return inCin.equals("R");
			case 18:
				return inCin.equals("S");
			case 19:
				return inCin.equals("T");
			case 20:
				return inCin.equals("U");
			case 21:
				return inCin.equals("V");
			case 22:
				return inCin.equals("W"); 
			case 23:
				return inCin.equals("X");
			case 24:
				return inCin.equals("Y");
			case 25:
				return inCin.equals("Z");

			default:
				return false;
		}
	}

	public static String ValidazioneCin(String bufStringa)
	{
		int cinStringa = 0;

		for( int i=0; i != bufStringa.length(); i++ )
		{
			// For i = 1 To Len(bufStringa)
			//   cinStringa = cinStringa + (Val(Asc(Mid(bufStringa, i, 1))) * i)
			// Next i
			cinStringa += ((int)bufStringa.charAt(i)) * (i+1);
		}
		cinStringa = cinStringa % 36;
		return ConvertiNumeroValore(cinStringa);
	}

	private static String ConvertiNumeroValore(int cinStringa)
	{
		switch (cinStringa)
		{
			case 0: return "Z";
			case 1: return "0";
			case 2: return "1";
			case 3: return "2";
			case 4: return "3";
			case 5: return "4";
			case 6: return "5";
			case 7: return "6";
			case 8: return "7";
			case 9: return "8";
			case 10: return "9";
			case 11: return "A";
			case 12: return "B";
			case 13: return "C";
			case 14: return "D";
			case 15: return "E";
			case 16: return "F";
			case 17: return "G";
			case 18: return "H";
			case 19: return "I";
			case 20: return "J";
			case 21: return "K";
			case 22: return "L";
			case 23: return "M";
			case 24: return "N";
			case 25: return "O";
			case 26: return "P";
			case 27: return "Q";
			case 28: return "R";
			case 29: return "S";
			case 30: return "T";
			case 31: return "U";
			case 32: return "V";
			case 33: return "W";
			case 34: return "X";
			case 35: return "Y";
			case 36: return "Z";
		}
		return "0";
	}


	public static boolean CheckIBAN_Fast( String iban )
	{
		if (iban.length() < 2 || iban.charAt(0) == ' ' || iban.charAt(1) == ' ') return false;

		int checksum = 0;
		int ibanLength = iban.length();
		for (int charIndex = 0; charIndex < ibanLength; charIndex++)
		{
			if (iban.charAt(charIndex) == ' ') continue;

			int value;
			int c = iban.charAt((charIndex + 4) % ibanLength);
			if ((c >= '0') && (c <= '9'))
			{
				value = c - '0';
			}
			else if ((c >= 'A') && (c <= 'Z'))
			{
				value = c - 'A';
				checksum = (checksum * 10 + (value / 10 + 1)) % 97;
				value %= 10;
			}
			else if ((c >= 'a') && (c <= 'z'))
			{
				value = c - 'a';
				checksum = (checksum * 10 + (value / 10 + 1)) % 97;
				value %= 10;
			}
			else
				return false;

			checksum = (checksum * 10 + value) % 97;
		}
		return checksum == 1;
	}

	public static boolean CheckIBAN(String iban) {
		
		
		String newIban = iban.replace(" ","").trim();

        // Check that the total IBAN length is correct as per the country. If not, the IBAN is invalid. We could also check
        // for specific length according to country, but for now we won't
        if (newIban.length() < IBANNUMBER_MIN_SIZE || newIban.length() > IBANNUMBER_MAX_SIZE) {
            return false;
        }

        // Move the four initial characters to the end of the string.
        newIban = newIban.substring(4) + newIban.substring(0, 4);

        // Replace each letter in the string with two digits, thereby expanding the string, where A = 10, B = 11, ..., Z = 35.
        StringBuilder numericAccountNumber = new StringBuilder();
        for (int i = 0;i < newIban.length();i++) {
            numericAccountNumber.append(Character.getNumericValue(newIban.charAt(i)));
        }

        // Interpret the string as a decimal integer and compute the remainder of that number on division by 97.
        BigInteger ibanNumber = new BigInteger(numericAccountNumber.toString());
        return ibanNumber.mod(IBANNUMBER_MAGIC_NUMBER).intValue() == 1;
	}
	
	public static boolean _CheckIBAN(String iban)
	{
		if (iban == null || iban.equals("")|| iban.trim().equals("1")) return false;
		if (iban.trim().length() < 2) return false;

		if (! "".equals(ONLYNumbers(iban.trim().substring(0, 2))))
		{
			return false;
		}

		String bufStringa = iban;
		if( bufStringa.contains(" " ) ) bufStringa = iban.replace(" ", "").toUpperCase();
		bufStringa = bufStringa.substring(4) + bufStringa.substring(0, 4); // Mid(bufStringa, 5) & Mid(bufStringa, 1, 4)

		StringBuilder sb = new StringBuilder(); 
		for (int i = 0; i < bufStringa.length(); i++)
		{
			char bsi = bufStringa.charAt(i); //.substring(i, 1);
			switch (bsi)
			{
				case 'A':
					sb.append("10");
					break;
				case 'B':
					sb.append("11");
					break;
				case 'C':
					sb.append("12");
					break;
				case 'D':
					sb.append("13");
					break;
				case 'E':
					sb.append("14");
					break;
				case 'F':
					sb.append("15");
					break;
				case 'G':
					sb.append("16");
					break;
				case 'H':
					sb.append("17");
					break;
				case 'I':
					sb.append("18");
					break;
				case 'J':
					sb.append("19");
					break;
				case 'K':
					sb.append("20");
					break;
				case 'L':
					sb.append("21");
					break;
				case 'M':
					sb.append("22");
					break;
				case 'N':
					sb.append("23");
					break;
				case 'O':
					sb.append("24");
					break;
				case 'P':
					sb.append("25");
					break;
				case 'Q':
					sb.append("26");
					break;
				case 'R':
					sb.append("27");
					break;
				case 'S':
					sb.append("28");
					break;
				case 'T':
					sb.append("29");
					break;
				case 'U':
					sb.append("30");
					break;
				case 'V':
					sb.append("31");
					break;
				case 'W':
					sb.append("32");
					break;
				case 'X':
					sb.append("33");
					break;
				case 'Y':
					sb.append("34");
					break;
				case 'Z':
					sb.append("35");
					break;
				default:
					sb.append(bsi);
					break;
			}
		}

		String chkIban = sb.toString();
		int checkModulo = ValidateIBAN(chkIban, 97);
		return checkModulo == 1;
	}

	private static int ValidateIBAN(String IBAN, int modulo)
	{
		int i = 1;
		Integer bufModulo = 0;

		do
		{
			int Numero;
			if (i == 1)
			{    //first time
				try {
					Numero = Integer.parseInt(IBAN.substring(i-1, i-1+9));
				} catch (Exception ex) {
					return 0;
				}
				i = 10;
			}
			else
			{
				//int v = 9 - bufModulo.toString().trim().length();
				//if (IBAN.length() < (i + v)) v += (IBAN.length() - i - v);

				try {
					Numero = Integer.parseInt(bufModulo + IBAN.substring(i-1, Math.min(i-1+9-bufModulo.toString().trim().length(),IBAN.length())));	
					i = i + (9-bufModulo.toString().trim().length());
				} catch(Exception ex) {
					return 0;
				}
				//i += v;
				
				//Numero = CLng(bufModulo + Mid(IBAN, i, 9 - Len(Util.Trim(Str(bufModulo)))));
				//i = i + (9 - Len(Util.Trim(Str(bufModulo))));
			}

			bufModulo = Numero % modulo;
		} while (i < IBAN.length());

		return bufModulo;
	}

	//public static bool CheckIBAN(String iban, String abi)
	//{
	//	if( iban.IndexOf(" ")>=0 ) iban = iban.Replace(" ", String.Empty);
	//	String sAbi = Mid(iban, 6, 5);
	//	return sAbi.CompareTo(abi) == 0;

	//	//String sAbi, sCab, sCC, sCin, CodicePaese, CheckDigit;
	//	//ScorporoIBAN(iban, out sAbi, out sCab, out sCC, out sCin, out CodicePaese, out CheckDigit);
	//	//return sAbi.CompareTo(abi) == 0;
	//}

	public static IBANScorporato ScorporoIBAN(String iban)
	{
		iban = iban.replace(" ", "");

		IBANScorporato ibanScorporato = new IBANScorporato();
		
		ibanScorporato.setAbi(Mid(iban, 6, 5));
		ibanScorporato.setCab( Mid(iban, 11, 5));
		ibanScorporato.setCC (Mid(iban, 16, 12));
		ibanScorporato.setCin (Mid(iban, 5, 1));
		ibanScorporato.setCodicePaese (Mid(iban, 1, 2));
		ibanScorporato.setCheckDigit (Mid(iban, 3, 2));
		
		return ibanScorporato;
	}

	private static String Mid(String Record, int Start, int Length)
	{
		if (Record == null || "".equals(Record)) 
			return "";
		if (Record.length() >= (Start + Length - 1)) 
			return Record.substring(Start - 1, Length);
		if (Record.length() > Start) 
			return Record.substring(Start - 1);
		return "";
	}


	public static boolean EseguiControlloCaratteriAmmessi(String inCampo, String inCaratteriValidi)
	{
		if ((ONLY(inCampo.toUpperCase(), inCaratteriValidi.toUpperCase())).length() != (inCampo.length()))
		{
			return false;
		}
		else
		{
			return true;
		}
	}
}


