/*
* 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 java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * @author Dario
 * 
 */
public class XmlUtils
{
  public static Date parseDate(String s)
  {
    if(s == null)
      return null;

    if (!isValidDate(s))
      return null;
    
    try
    {
      SimpleDateFormat xmlFormat = new SimpleDateFormat("yyyy-MM-dd");
      return xmlFormat.parse(s);
    }
    catch(ParseException e)
    {
      return null;
    }
  }
  
  public static Date parseTimestamp(String s)
  {
    if(s == null)
      return null;

    try
    {
      SimpleDateFormat xmlFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
      return xmlFormat.parse(s);
    }
    catch(ParseException e)
    {
      return null;
    }
  }
  
  public static String formatDate(Date d)
  {
    SimpleDateFormat xmlFormat = new SimpleDateFormat("yyyy-MM-dd");
    return d != null ? xmlFormat.format(d) : null;
  }


  public static Integer parseInteger(String s)
  {
    if(s == null)
      return null;

    try
    {
      return new Integer(s);
    }
    catch(NumberFormatException e)
    {
      return null;
    }
  }
  

  public static String formatInteger(Integer i)
  {
    return i != null ? i.toString() : null;
  }


  public static BigDecimal parseAmount(String s)
  {
    if(s == null)
      return null;

    try
    {
      DecimalFormatSymbols dfs = new DecimalFormatSymbols();
      dfs.setDecimalSeparator('.');
      DecimalFormat amountFormat = new DecimalFormat("0.00", dfs);
      BigDecimal value = new BigDecimal(amountFormat.parse(s).doubleValue());
      return value;
    }
    catch(ParseException e)
    {
      return null;
    }
  }
  
  
  public static String formatAmount(BigDecimal bd)
  {
    DecimalFormatSymbols dfs = new DecimalFormatSymbols();
    dfs.setDecimalSeparator('.');
    DecimalFormat amountFormat = new DecimalFormat("0.00", dfs);
    return bd != null ? amountFormat.format(bd.doubleValue()) : null;
  }


  public static BigDecimal parsePrice(String s)
  {
    if(s == null)
      return null;

    try
    {
      DecimalFormatSymbols dfs = new DecimalFormatSymbols();
      dfs.setDecimalSeparator('.');
      DecimalFormat priceFormat = new DecimalFormat("0.00###", dfs);

      return new BigDecimal(priceFormat.parse(s).doubleValue());
    }
    catch(ParseException e)
    {
      return null;
    }
  }
  
  
  public static String formatPrice(BigDecimal bd)
  {
    DecimalFormatSymbols dfs = new DecimalFormatSymbols();
    dfs.setDecimalSeparator('.');
    DecimalFormat priceFormat = new DecimalFormat("0.00###", dfs);

    return bd != null ? priceFormat.format(bd.doubleValue()) : null;
  }


  public static BigDecimal parsePerc(String s)
  {
    if(s == null)
      return null;

    try
    {
      DecimalFormatSymbols dfs = new DecimalFormatSymbols();
      dfs.setDecimalSeparator('.');
      DecimalFormat percFormat = new DecimalFormat("0.###", dfs);
      return new BigDecimal(percFormat.parse(s).doubleValue());
    }
    catch(ParseException e)
    {
      return null;
    }
  }
  
  
  public static String formatPerc(BigDecimal bd)
  {
    DecimalFormatSymbols dfs = new DecimalFormatSymbols();
    dfs.setDecimalSeparator('.');
    DecimalFormat percFormat = new DecimalFormat("0.###", dfs);
    return bd != null ? percFormat.format(bd.doubleValue()) : null;
  }


  public static BigDecimal parseQty(String s)
  {
    if(s == null)
      return null;

    try
    {
      DecimalFormatSymbols dfs = new DecimalFormatSymbols();
      dfs.setDecimalSeparator('.');
      DecimalFormat qtyFormat = new DecimalFormat("0.###", dfs);
      return new BigDecimal(qtyFormat.parse(s).doubleValue());
    }
    catch(ParseException e)
    {
      return null;
    }
  }
  
  
  public static String formatQty(BigDecimal bd)
  {
    DecimalFormatSymbols dfs = new DecimalFormatSymbols();
    dfs.setDecimalSeparator('.');
    DecimalFormat qtyFormat = new DecimalFormat("0.###", dfs);
    return bd != null ? qtyFormat.format(bd.doubleValue()) : null;
  }
  
  
  public static String escapeXmlString(String s)
  {
    if(s == null)
      return null;
    
    return s
      .replaceAll("&", "&amp;")
      .replaceAll("<","&lt;")
      .replaceAll(">","&gt;");
  }
  
  
  public static String readText(Node node)
  {
    StringBuffer sb = new StringBuffer();
    
    NodeList list = node.getChildNodes();
    for(int i = 0; i < list.getLength(); ++i)
    {
      Node child = list.item(i);
      if(child.getNodeType() == Node.TEXT_NODE)
        sb.append(child.getNodeValue().trim());
      else if(child.getNodeType() == Node.CDATA_SECTION_NODE)
        sb.append(child.getNodeValue().trim());
    }
    
    return sb.toString();
  }
  
  
  public static String readText(Element parent, String childName)
  {
    Node node = getSingleChildNode(parent, childName);
    if(node == null)
      return null;
    
    return readText(node);
  }
  
  
  public static Date readDate(Node node)
  {
    String s = readText(node);
    if(s == null)
      return null;
    
    return parseDate(s);
  }
  
  
  public static Date readDate(Element parent, String childName)
  {
    String s = readText(parent, childName);
    if(s == null)
      return null;
    
    return parseDate(s);
  }
  
  
  public static Date readTimestamp(Element parent, String childName)
  {
    String s = readText(parent, childName);
    if(s == null)
      return null;
    
    return parseTimestamp(s);
  }
  
  
  public static Integer readInteger(Node node)
  {
    String s = readText(node);
    if(s == null)
      return null;
    
    return parseInteger(s);
  }
  
  
  public static Integer readInteger(Element parent, String childName)
  {
    String s = readText(parent, childName);
    if(s == null)
      return null;
    
    return parseInteger(s);
  }
  
  
  public static BigDecimal readAmount(Node node)
  {
    String s = readText(node);
    if(s == null)
      return null;
    
    return parseAmount(s);
  }
  
  
  public static BigDecimal readAmount(Element parent, String childName)
  {
    String s = readText(parent, childName);
    if(s == null)
      return null;
    
    return parseAmount(s);
  }
  
  
  public static BigDecimal readPerc(Node node)
  {
    String s = readText(node);
    if(s == null)
      return null;
    
    return parsePerc(s);
  }
  
  
  public static BigDecimal readPerc(Element parent, String childName)
  {
    String s = readText(parent, childName);
    if(s == null)
      return null;
    
    return parsePerc(s);
  }
  
  
  public static BigDecimal readPercDafne(Node node)
  {
    String s = readText(node);
    if(s == null)
      return null;
    
    return parsePerc(s.replace(',', '.'));
  }
  
  
  public static BigDecimal readPercDafne(Element parent, String childName)
  {
    String s = readText(parent, childName);
    if(s == null)
      return null;
    
    return parsePerc(s.replace(',', '.'));
  }
  
  
  public static BigDecimal readQty(Node node)
  {
    String s = readText(node);
    if(s == null)
      return null;
    
    return parseQty(s);
  }
  
  
  public static BigDecimal readQty(Element parent, String childName)
  {
    String s = readText(parent, childName);
    if(s == null)
      return null;
    
    return parseQty(s);
  }
  
  
  public static BigDecimal readPrice(Node node)
  {
    String s = readText(node);
    if(s == null)
      return null;
    
    return parsePrice(s);
  }
  
  
  public static BigDecimal readPrice(Element parent, String childName)
  {
    String s = readText(parent, childName);
    if(s == null)
      return null;
    
    return parsePrice(s);
  }
  
  
  public static Node getSingleChildNode(Element parent, String childName)
  {
    if(parent == null)
      return null;
    
    NodeList list = parent.getElementsByTagName(childName);
    if(list == null || list.getLength() == 0)
      return null;

    return list.item(0);
  }
  
  
  public static Node getSingleDirectChildNode(Element parent, String childName)
  {
    if(parent == null)
      return null;
    
    NodeList list = parent.getChildNodes();
    for(int i = 0; i < list.getLength(); ++i)
    {
      Node node = list.item(i);
      if(node.getNodeType() != Node.ELEMENT_NODE)
        continue;
      
      if(node.getNodeName().equals(childName))
        return node;
    }
    
    return null;
  }

  public static boolean isIBAN(String iban)
  {
    iban = iban.trim().toUpperCase();
    try
    {
      // 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"));
    }
    catch(Exception e)
    {
      return false;
    }
  }
  
  public static boolean isValidDate(String s)
  {
    SimpleDateFormat sdf = null;
    SimpleDateFormat longDateFormat = new SimpleDateFormat(
    "yyyy-MM-dd");
    
    Pattern p = Pattern.compile("^\\d{4}-\\d{2}-\\d{2}$");
    Matcher m = p.matcher(s);
    if(m.find())
      sdf = longDateFormat;
    else
    {
        return false;
    }

    Date parsedDate = null;
    try
    {
      parsedDate = sdf.parse(s);
    }
    catch(ParseException e)
    {
      e.printStackTrace();
      return false;
    }

    String[] dateparts = s.split("-");
    String year = dateparts[0];
    String month = dateparts[1];
    String day = dateparts[2];
    
    String fpd = sdf.format(parsedDate);
    return fpd.equals(year + "-" + month + "-" + day);
  }
  
}
