/**
 * 
 */
package at.gv.egiz.pdfas.utils;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.apache.commons.codec.binary.Base64;

import at.knowcenter.wag.egov.egiz.pdf.BinarySignatureHolder;
import at.knowcenter.wag.egov.egiz.pdf.SignatureHolder;
import at.knowcenter.wag.egov.egiz.pdf.TextualSignatureHolder;

/**
 * Contains helpful methods for building data hashed.
 * 
 * <p>
 * Data hashes are useful for summarizing the signed data of signatures for
 * debugging and testing purposes. Do not use these hashes for signatures.
 * </p>
 * <p>
 * A data hash is always a Base64 encoded String.
 * </p>
 * 
 * @author wprinz
 * 
 */
public final class DataHashUtils
{

  /**
   * 
   * @param text
   * @return
   */
  public static String buildDataHash(String text)
  {
    try
    {
      MessageDigest md = getMessageDigest();
      // probable performance leak for very large texts
      md.update(text.getBytes("UTF-8"));
      byte[] rawDigest = md.digest();

      return encodeDigest(rawDigest);
    }
    catch (UnsupportedEncodingException e)
    {
      throw new RuntimeException(e);
    }
  }

  public static String buildDataHash(byte[] data)
  {
    MessageDigest md = getMessageDigest();
    md.update(data);
    byte[] rawDigest = md.digest();

    return encodeDigest(rawDigest);
  }

  public static String buildDataHash(InputStream is)
  {
    try
    {
      MessageDigest md = getMessageDigest();

      DigestInputStream dis = new DigestInputStream(is, md);

      byte[] temp = new byte[1024];
      int i = 0;
      while (dis.read(temp) >= 0)
      {
        // this just keeps the compiler from optimizing this loop away
        i++;
      }
      dis.close();

      byte[] rawDigest = md.digest();

      return encodeDigest(rawDigest);
    }
    catch (IOException e)
    {
      throw new RuntimeException(e);
    }
  }
  
  public static String buildDataHash(SignatureHolder sh)
  {
    if (sh instanceof TextualSignatureHolder)
    {
      TextualSignatureHolder tsh = (TextualSignatureHolder) sh;
      String signedText = tsh.getSignedText();
      return buildDataHash(signedText);
    }
    
    {
      BinarySignatureHolder bsh = (BinarySignatureHolder) sh;
      InputStream is = bsh.getSignedPdf().createInputStream();
      return buildDataHash(is);
    }
  }

  protected static MessageDigest getMessageDigest()
  {
    try
    {
      MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
      return sha1;
    }
    catch (NoSuchAlgorithmException e)
    {
      throw new RuntimeException(e);
    }
  }

  protected static String encodeDigest(byte[] rawDigest)
  {
    try
    {
      byte[] encoded = Base64.encodeBase64(rawDigest);
      String str = new String(encoded, "US-ASCII");
      return str;
    }
    catch (UnsupportedEncodingException e)
    {
      throw new RuntimeException(e);
    }
  }
}