/*
* Copyright 2014 - LAit SpA
*				 Realizzato da Icona Management srl su commessa LAit SpA
* Copyright 2015- LAit SpA
*                                                  Aggiornato da LAit SpA
*
* Concesso in licenza a norma dell'EUPL, versione 1.1 o
* successive dell'EUPL (la "Licenza")– non appena saranno
* approvate dalla Commissione europea;
* Non è possibile utilizzare l'opera salvo nel rispetto della Licenza.
* È possibile ottenere una copia della Licenza al seguente indirizzo:
*
* http://ec.europa.eu/idabc/eupl
*
* Salvo diversamente indicato dalla legge applicabile o
* concordato per iscritto, il software distribuito secondo
* i termini della Licenza è distribuito "TAL QUALE",
* SENZA GARANZIE O CONDIZIONI DI ALCUN TIPO,
* esplicite o implicite.
* Si veda la Licenza per la lingua specifica che disciplina
* le autorizzazioni e le limitazioni secondo i termini della
* Licenza.
*/
/**
 *
 */
package it.laitspa.cpf.util.misc;

import it.laitspa.cpf.util.misc.DateUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author Dario
 * 
 */
public class FormUtils
{
  public static final String EMPTY_SELECTION = "__EMPTY__";
  public static final String NULL_VALUE      = "_NL_";

  public static BigDecimal   minus           = new BigDecimal("-1");
  public static BigDecimal   zero            = new BigDecimal("0");

  public static String makeQueryLikeParameter(String s)
  {
    return makeQueryLikeParameter(s, false);
  }

  public static String makeQueryLikeParameter(String s, boolean uppercase)
  {
    if(isEmpty(s))
      return null;

    s = s.trim();

    if(uppercase)
      s = s.toUpperCase();

    return "%" + s + "%";
  }

  public static String makeQueryParameter(String s)
  {
    if(isEmpty(s))
      return null;

    return s.trim();
  }

  public static String makeUpperQueryParameter(String s)
  {
    if(isEmpty(s))
      return null;

    return s.trim().toUpperCase();
  }

  public static Integer makeIntegerQueryParameter(String s)
  {
    if(isEmpty(s))
      return null;

    if(!IntegerUtils.isValid(s))
      return null;

    try
    {
      return IntegerUtils.parse(s);
    }
    catch(Exception e)
    {
      // Should never happen.
      //
      return null;
    }
  }

  public static Long makeLongQueryParameter(String s)
  {
    if(isEmpty(s))
      return null;

    if(!IntegerUtils.isValid(s))
      return null;

    try
    {
      return IntegerUtils.parseLong(s);
    }
    catch(Exception e)
    {
      // Should never happen.
      //
      return null;
    }
  }

  public static Integer makeIntegerQueryParameterDefZero(String s)
  {
    Integer result = makeIntegerQueryParameter(s);

    return result == null ? new Integer(0) : result;
  }

  public static BigDecimal makeDecimalQueryParameter(String s)
  {
    if(isEmpty(s))
      return null;

    if(!FormUtils.isDecimal(s))
      return null;

    try
    {
      return DecimalUtils.parse(s);
    }
    catch(Exception e)
    {
      // Should never happen.
      //
      return null;
    }
  }

  public static BigDecimal makePositiveDecimalQueryParameter(String s)
  {
    if(isEmpty(s))
      return null;

    if(!FormUtils.isDecimal(s))
      return null;

    try
    {
      BigDecimal bd = DecimalUtils.parse(s);
      return bd.abs();
    }
    catch(Exception e)
    {
      // Should never happen.
      //
      return null;
    }
  }

  public static BigDecimal makeNegativeDecimalQueryParameter(String s)
  {
    if(isEmpty(s))
      return null;

    if(!FormUtils.isDecimal(s))
      return null;

    try
    {
      BigDecimal bd = DecimalUtils.parse(s);
      BigDecimal nbd = bd.abs().multiply(minus);
      return nbd;
    }
    catch(Exception e)
    {
      // Should never happen.
      //
      return null;
    }
  }

  public static Date makeDateQueryParameter(String s)
  {
    if(isEmpty(s))
      return null;

    if(!DateUtils.isValid(s))
      return null;

    try
    {
      return DateUtils.parse(s);
    }
    catch(Exception e)
    {
      // Should never happen.
      //
      return null;
    }
  }

  public static Date makeDateTimeQueryParameter(String s)
  {
    if(isEmpty(s))
      return null;

    if(!DateUtils.isValidDateTime(s))
      return null;

    try
    {
      return DateUtils.parseDateTime(s);
    }
    catch(Exception e)
    {
      // Should never happen.
      //
      return null;
    }
  }

  public static Date makeDate(String s)
  {
    if(isEmpty(s))
      return null;

    if(!DateUtils.isValid(s))
      return null;

    try
    {
      return DateUtils.parse(s);
    }
    catch(Exception e)
    {
      // Should never happen.
      //
      return null;
    }
  }

  public static String makeQueryParameterFromSelection(String s)
  {
    if(isEmptySelection(s))
      return null;

    return s.trim();
  }

  public static String makeUpperQueryParameterFromSelection(String s)
  {
    if(isEmptySelection(s))
      return null;

    return s.trim().toUpperCase();
  }

  public static Integer makeIntegerQueryParameterFromSelection(String s)
  {
    if(isEmptySelection(s))
      return null;

    return new Integer(s.trim());
  }

  public static Integer makeIntegerQueryParameterFromSelection(Integer s)
  {
    return s == null ? null : s.equals(new Integer(0)) ? null : s;
  }

  public static String makeGuiString(String s)
  {
    if(s == null)
      return "";

    return s.trim();
  }

  public static String makeGuiString(String s, char padChar, int length)
  {
    if(s == null)
      return "";

    return makePadded(s.trim(), padChar, length);
  }

  public static String makeGuiString(String s, int maxLength)
  {
    if(s == null)
      return "";

    String buffer = s.trim();
    if(buffer.length() > maxLength)
      buffer = buffer.substring(0, 17) + "...";
    return buffer;
  }

  public static String makeGuiString(Integer i)
  {
    if(i == null)
      return "";

    return i.toString();
  }

  public static String makeGuiString(Long i)
  {
    if(i == null)
      return "";

    return i.toString();
  }

  public static String makeGuiString(Object o)
  {
    if(o == null)
      return "";

    return o.toString();
  }

  public static String makeGuiString(int i)
  {
    return Integer.toString(i);
  }

  public static String makeGuiString(long i)
  {
    return Long.toString(i);
  }

  public static String makeGuiString(Date d)
  {
    if(d == null)
      return "";

    return DateUtils.toLongDateString(d);
  }

  public static String makeGuiStringTs(Date d)
  {
    if(d == null)
      return "";

    return DateUtils.toLongDateTimeString(d);
  }

  public static Boolean makeBooleanQueryParameter(String s)
  {

    if((s == null) || (s.trim().length() == 0))
      return null;
    else if(s.equalsIgnoreCase("true") || s.equalsIgnoreCase("Y"))
      return true;
    else if(s.equalsIgnoreCase("false") || s.equalsIgnoreCase("N"))
      return false;
    else
      return null;

  }

  public static String makeGuiStringShort(Date d)
  {
    if(d == null)
      return "";

    return DateUtils.toShortDateString(d);
  }

  public static String makeGuiStringSiNo(Boolean b)
  {
    if(b == null)
      return "";

    return b.booleanValue() ? "S" : "N";
  }

  public static String makeGuiString(BigDecimal b)
  {
    return DecimalUtils.toString(b);
  }

  public static String makeGuiString(BigDecimal b, boolean twoDecimals)
  {
    if(b == null)
      return "";

    return DecimalUtils.toString(b, twoDecimals);
  }

  public static String makeGuiStringAmount(BigDecimal b)
  {
    if(b == null)
      return "";

    return AmountUtils.toStringAmount(b);
  }

  public static String makeGuiStringPositiveAmount(BigDecimal b)
  {
    if(b == null)
      return "";

    return AmountUtils.toStringPositiveAmount(b);
  }

  public static String makeGuiStringPrice(BigDecimal b)
  {
    if(b == null)
      return "";

    return AmountUtils.toStringPrice(b);
  }

  public static String makeGuiStringPerc(BigDecimal b)
  {
    if(b == null)
      return "";

    return AmountUtils.toStringPerc(b);
  }

  public static String makeGuiString(Boolean d)
  {
    if(d == null)
      return "N";
    if(d == Boolean.TRUE)
      return "S";
    else
      return "N";
  }

  public static String makeGuiSelection(String s)
  {
    if(isEmpty(s))
      return EMPTY_SELECTION;

    return s.trim();
  }

  public static String makeGuiSelection(Integer i)
  {
    if(i == null)
      return EMPTY_SELECTION;

    return i.toString();
  }

  public static boolean isEmpty(String p)
  {
    return p == null || p.trim().length() == 0 || p.trim().equals(NULL_VALUE);
  }

  public static boolean isEmptySelection(String p)
  {
    return p == null || p.trim().length() == 0 || p.equals(EMPTY_SELECTION)
        || p.trim().equals(NULL_VALUE);
  }

  public static boolean isEmpty(BigDecimal d)
  {
    return d == null;
  }

  public static boolean isProvincia(String s) // poi lo tolgo
  {
    ArrayList<String> provinceList = new ArrayList<String>();
    provinceList.add("AG");
    provinceList.add("AL");
    provinceList.add("AN");
    provinceList.add("AO");
    provinceList.add("AP");
    provinceList.add("AQ");
    provinceList.add("AR");
    provinceList.add("AT");
    provinceList.add("AV");
    provinceList.add("BA");
    provinceList.add("BG");
    provinceList.add("BI");
    provinceList.add("BL");
    provinceList.add("BN");
    provinceList.add("BO");
    provinceList.add("BR");
    provinceList.add("BS");
    provinceList.add("BZ");
    provinceList.add("CA");
    provinceList.add("CB");
    provinceList.add("CE");
    provinceList.add("CH");
    provinceList.add("CL");
    provinceList.add("CN");
    provinceList.add("CO");
    provinceList.add("CR");
    provinceList.add("CS");
    provinceList.add("CT");
    provinceList.add("CZ");
    provinceList.add("EN");
    provinceList.add("FC");
    provinceList.add("FE");
    provinceList.add("FG");
    provinceList.add("FI");
    provinceList.add("FR");
    provinceList.add("GE");
    provinceList.add("GO");
    provinceList.add("GR");
    provinceList.add("IM");
    provinceList.add("IS");
    provinceList.add("KR");
    provinceList.add("LC");
    provinceList.add("LE");
    provinceList.add("LI");
    provinceList.add("LO");
    provinceList.add("LT");
    provinceList.add("LU");
    provinceList.add("MC");
    provinceList.add("ME");
    provinceList.add("MI");
    provinceList.add("MN");
    provinceList.add("MO");
    provinceList.add("MS");
    provinceList.add("MT");
    provinceList.add("NA");
    provinceList.add("NO");
    provinceList.add("NU");
    provinceList.add("OR");
    provinceList.add("PA");
    provinceList.add("PC");
    provinceList.add("PD");
    provinceList.add("PE");
    provinceList.add("PG");
    provinceList.add("PI");
    provinceList.add("PN");
    provinceList.add("PO");
    provinceList.add("PR");
    provinceList.add("PS");
    provinceList.add("PT");
    provinceList.add("PV");
    provinceList.add("PZ");
    provinceList.add("RA");
    provinceList.add("RC");
    provinceList.add("RE");
    provinceList.add("RG");
    provinceList.add("RI");
    provinceList.add("RM");
    provinceList.add("RN");
    provinceList.add("RO");
    provinceList.add("SA");
    provinceList.add("SI");
    provinceList.add("SO");
    provinceList.add("SP");
    provinceList.add("SR");
    provinceList.add("SS");
    provinceList.add("SV");
    provinceList.add("TA");
    provinceList.add("TE");
    provinceList.add("TN");
    provinceList.add("TO");
    provinceList.add("TP");
    provinceList.add("TR");
    provinceList.add("TS");
    provinceList.add("TV");
    provinceList.add("UD");
    provinceList.add("VA");
    provinceList.add("VB");
    provinceList.add("VC");
    provinceList.add("VE");
    provinceList.add("VI");
    provinceList.add("VR");
    provinceList.add("VT");
    provinceList.add("VV");

    return provinceList.contains(s.toUpperCase());
  }

  public static boolean isCodicePartitaIVA(String s)
  {
    // Must be numeric, 11 digits.
    //
    Pattern p = Pattern.compile("^\\d{11}$");
    Matcher m = p.matcher(s);
    if(!m.find())
      return false;

    // Verify check digit.
    //

    // Sum odd digits (including check digit).
    //
    int odd = 0;
    for(int i = 0; i < 11; i += 2)
    {
      int digit = s.getBytes()[i] - '0';
      odd += digit;
    }

    // Sum doubled even digits counting digits >= 5.
    //
    int upcnt = 0;
    int even = 0;
    for(int i = 1; i < 11; i += 2)
    {
      int digit = s.getBytes()[i] - '0';
      upcnt += digit >= 5 ? 1 : 0;
      even += digit * 2;
    }

    // Sum up everything.
    //
    int t = odd + even + upcnt;

    // Mod 10 must be zero.
    //
    return (t % 10) == 0;
  }

  public static boolean isCodiceFiscale(String s)
  {
    if(s != null)
      s = s.toUpperCase();
    int odd[] =
        { 1, 0, 5, 7, 9, 13, 15, 17, 19, 21, 2, 4, 18, 20, 11, 3, 6, 8, 12, 14, 16, 10, 22, 25, 24,
            23 };

    if(s.length() == 0)
      return false;

    if(s.length() != 16)
      return false;

    for(int i = 0; i < 16; i++)
    {
      int c = s.charAt(i);
      if(!(c >= '0' && c <= '9' || c >= 'A' && c <= 'Z'))
        return false;
    }

    int sum = 0;

    for(int i = 1; i <= 13; i += 2)
    {
      int c = s.charAt(i);
      if(c >= '0' && c <= '9')
        sum = sum + c - '0';
      else
        sum = sum + c - 'A';
    }

    for(int i = 0; i <= 14; i += 2)
    {
      int c = s.charAt(i);
      if(c >= '0' && c <= '9')
        c = c - '0' + 'A';
      sum = sum + odd[c - 'A'];
    }

    return(sum % 26 + 'A' == s.charAt(15));
  }

  public static boolean isInteger(String s)
  {
    // Use regex to quickly validate format.
    //
    Pattern p = Pattern.compile("^[+-]{0,1}\\d+$");
    Matcher m = p.matcher(s);
    return m.find();
  }

  public static boolean isDecimal(String s)
  {
    // Use regex to quickly validate format.
    //
    Pattern p = Pattern.compile("^[+-]{0,1}\\d+(\\,\\d*){0,1}$");
    Matcher m = p.matcher(s);
    return m.find();
  }

  /**
   * Decimale con massimo tre cifre, un punto, e una cifra decimale opzionale
   */
  public static boolean isDecimal3_1(String s)
  {
    // Use regex to quickly validate format.
    //
    Pattern p = Pattern.compile("^([0-9]|[1-9][0-9]{1}|[1-9][0-9]{2})(\\,[0-9]{1}){0,1}$");
    Matcher m = p.matcher(s);
    return m.find();
  }

  /**
   * Decimale con massimo sei cifre, un punto, e due cifra decimali opzionali
   */
  public static boolean isDecimal6_2(String s)
  {
    // Use regex to quickly validate format.
    //
    Pattern p =
        Pattern
            .compile("^([0-9]|[1-9][0-9]{1}|[1-9][0-9]{2}|[1-9][0-9]{3}|[1-9][0-9]{4}|[1-9][0-9]{5})(\\,[0-9]{1}||[0-9]{2}){0,1}$");
    Matcher m = p.matcher(s);
    return m.find();
  }

  public static boolean isCAP(String s)
  {
    // Use regex to quickly validate format.
    //
    Pattern p = Pattern.compile("^\\d{5}$");
    Matcher m = p.matcher(s);
    return m.find();
  }

  public static boolean isEmailAddress(String s)
  {
    // Use regex to quickly validate format.
    //
    Pattern p =
        Pattern
            .compile("^([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)$");
    Matcher m = p.matcher(s);
    return m.find();
  }

  public static boolean isPhone(String s)
  {
    // Use regex to quickly validate format.
    //
    Pattern p = Pattern.compile("^(\\+){0,1}[0-9.-/ ]+$");
    Matcher m = p.matcher(s);
    return m.find();
  }

  public static boolean isPassword(String s)
  {
    // Use regex to quickly validate format.
    //
    Pattern p = Pattern.compile("^(?=.*[a-zA-Z]+.*)(?=.*[0-9]+.*)[0-9a-zA-Z]{8,}$");
    Matcher m = p.matcher(s);
    return m.find();
  }

  public static boolean isCodiceLibretto(String s)
  {
    // Use regex to quickly validate format.
    //
    Pattern p = Pattern.compile("^[a-zA-Z]{6}$");
    Matcher m = p.matcher(s);
    return m.find();
  }

  public static boolean isSezione(String s)
  {
    // Use regex to quickly validate format.
    //
    Pattern p = Pattern.compile("^\\w$");
    Matcher m = p.matcher(s);
    return m.find();
  }

  public static String escapeJavaScriptString(String s)
  {
    return replace(s, "'", "\\'");
  }

  private static String replace(String buffer, String find, String replace)
  {
    StringBuffer result = new StringBuffer();

    int startIdx = 0;
    int idxOld = 0;
    while((idxOld = buffer.indexOf(find, startIdx)) >= 0)
    {
      result.append(buffer.substring(startIdx, idxOld));
      result.append(replace);

      startIdx = idxOld + find.length();
    }

    result.append(buffer.substring(startIdx));

    return result.toString();
  }

  public static boolean isIBAN(String iban)
  {
    iban = iban.trim().toUpperCase();

    // Use regex to quickly validate format.
    //
    Pattern p = Pattern.compile("^[A-Z0-9]+$");
    Matcher m = p.matcher(iban);
    if(!m.find())
      return false;

    String s = iban.substring(4) + iban.substring(0, 4);

    String t = new String();
    for(int i = 0; i < s.length(); ++i)
    {
      char c = s.charAt(i);
      if(Character.isLetter(c))
        t += new Integer(c - 'A' + 10).toString();
      else if(Character.isDigit(c))
        t += c;
      else
        return false;
    }

    BigInteger bi = new BigInteger(t);
    BigInteger mod = bi.mod(new BigInteger("97"));

    return mod.equals(new BigInteger("1"));
  }

  public static String makePadded(String s, char c, int length)
  {
    StringBuffer sb = new StringBuffer();
    for(int i = 0; i < length; ++i)
      sb.append(c);

    sb.append(s);

    return sb.substring(sb.length() - length);
  }

  public static boolean isCodiceRegionale(String s)
  {
    // Use regex to quickly validate format.
    //
    Pattern p = Pattern.compile("^[SE]\\d{5}$|^\\d{6}$");
    Matcher m = p.matcher(s);
    return m.find();
  }

  public static String[] splitLines(String s)
  {
    String[] list = s.split("\r\n|\r|\n");
    return list;
  }

  public static boolean isWithinLength(String s, int length)
  {
    return s.trim().length() <= length;
  }
}
