package test;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.xml.transform.TransformerException;

import org.w3c.dom.Element;

import at.gv.egovernment.moa.util.Constants;
import at.gv.egovernment.moa.util.DOMUtils;
import at.gv.egovernment.moa.util.FileUtils;
import at.gv.egovernment.moa.util.StreamUtils;
import at.gv.egovernment.moa.util.XPathUtils;

import iaik.ixsil.algorithms.Transform;
import iaik.ixsil.algorithms.TransformImplExclusiveCanonicalXML;
import iaik.ixsil.exceptions.AlgorithmException;
import iaik.ixsil.exceptions.InitException;
import iaik.ixsil.exceptions.URIException;
import iaik.ixsil.init.IXSILInit;
import iaik.ixsil.util.URI;
import test.at.gv.egovernment.moa.MOATestCase;

/*
 * @author Paul Ivancsics
 * @version $Id$
 */
public class MOAIDTestCase extends MOATestCase implements Constants {

  public static final String XML_DECL =
    "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>";
  protected static final String nl = "\n";

  public MOAIDTestCase(String name) {
    super(name);
  }

  protected void initIxsil() throws InitException, URIException {
       IXSILInit.init(new URI("init/properties/init.properties"));
    // Switch on debug information
    IXSILInit.setPrintDebugLog(true);
  }
  //STRING <==> STRING
  protected void assertXmlEquals(String xml1, String xml2)
   throws AlgorithmException, IOException, InitException, URIException{
   initIxsil();
   String canXml1 = canonicalTransform(xml1);
   String canXml2 = canonicalTransform(xml2);
    assertEquals(canXml1, canXml2);  }
  // ELEMENT <==>  ELEMENT  
   protected void assertXmlEquals(Element xml1, Element xml2)  
    throws AlgorithmException, IOException, InitException , URIException, TransformerException{
   initIxsil();  
    assertEquals(canonicalTransform(DOMUtils.serializeNode(xml1)),canonicalTransform(DOMUtils.serializeNode(xml2)));
  }
  // INPUTSTREAM <==> INPUTSTREAM
  protected void assertXmlEquals(InputStream xml1, InputStream xml2)  
    throws AlgorithmException, IOException, InitException , URIException{
   initIxsil();  
    assertEquals(canonicalTransform(xml1),canonicalTransform(xml2));
  }
  // ELEMENT <==> STRING
  protected void assertXmlEquals(Element xml1, String xml2)  
 throws AlgorithmException, IOException, InitException , URIException, TransformerException {
   initIxsil();  
    assertEquals(canonicalTransform(xml1),canonicalTransform(xml2));
  }
  // ELEMENT <==> INPUTSTREAM
  protected void assertXmlEquals(Element xml1, InputStream xml2)  
    throws AlgorithmException, IOException, InitException , URIException, TransformerException{
   initIxsil();  
    assertEquals(canonicalTransform(xml1),canonicalTransform(xml2));
  }
  // STRING <==> INPUTSTREAM
    protected void assertXmlEquals(String xml1, InputStream xml2)  
    throws AlgorithmException, IOException, InitException , URIException{
   initIxsil();  
    assertEquals(canonicalTransform(xml1),canonicalTransform(xml2));
  }
      
  /**
   * Method canonicalTransform.
   * @param input as STRING
   * @return String
   */
  protected String canonicalTransform(String input)
    throws AlgorithmException, IOException {
    
    Transform tr = new TransformImplExclusiveCanonicalXML();
    InputStream s = new ByteArrayInputStream(input.getBytes("UTF-8"));
    tr.setInput(s, null);
    ByteArrayInputStream transResult = (ByteArrayInputStream) tr.transform();
    return killWhiteSpace(readString(transResult));
  }  
  /**
   * Method canonicalTransform.
   * @param input as Element
   * @return String
   */  
  protected String canonicalTransform(Element input)
    throws AlgorithmException, IOException {

    Transform tr = new TransformImplExclusiveCanonicalXML();  
    tr.setInput(XPathUtils.selectNodeList(input, XPathUtils.ALL_NODES_XPATH), null);
    ByteArrayInputStream transResult = (ByteArrayInputStream) tr.transform();
   
    return killWhiteSpace(readString(transResult));
  }

  /**
   * Method canonicalTransform.
   * @param input as InputStream
   * @return String
   */  
  protected String canonicalTransform(InputStream input)
    throws AlgorithmException, IOException {
  
    Transform tr = new TransformImplExclusiveCanonicalXML();  tr.setInput(input, null);
    ByteArrayInputStream transResult = (ByteArrayInputStream) tr.transform();
   
    return killWhiteSpace(readString(transResult));
  }

  public static String killWhiteSpace(String input) 
  {
  int start=0;
  int ende;
  String result;
  String middle;
  result = input;
  do {
    start = result.indexOf(">", start);
    ende = result.indexOf("<", start);  
    middle = result.substring(start+1,ende).trim();
    result = result.substring(0,start+1) +middle +  result.substring(ende,result.length());   
    start++;
  } while (result.indexOf("<", ende + 1)>0);
  
  return result;
  }
  
  /**
   * Method killExclusive.: The values startsWith and endsWith will be included into the answer.
   * @param input
   * @param startsWith
   * @param endsWith
   * @param newValue
   * @return String
   */
  public static String killExclusive(String input, String startsWith, String endsWith, String newValue)
 {
  int start=0;
  int ende;
  String result;
  result = input;
  do {
    start = result.indexOf(startsWith, start) + startsWith.length();
    ende = result.indexOf(endsWith, start);  
    result = result.substring(0,start) + newValue + result.substring(ende,result.length());   
    start++;
  } while (result.indexOf(startsWith, ende + 1)>0);
  
    return result;    
 }

  /**
   * Method killInclusive. : The values startsWith and endsWith will NOT be included into the answer.
   * @param input
   * @param startsWith
   * @param endsWith
   * @param newValue
   * @return String
   */
  public static String killInclusive(String input, String startsWith, String endsWith, String newValue)
 {
  int start=0;
  int ende;
  String result;
  result = input;
  do {
    start = result.indexOf(startsWith, start) + startsWith.length();
    ende = result.indexOf(endsWith, start);  
    result = result.substring(0,start - startsWith.length() ) + newValue + result.substring(ende + endsWith.length(),result.length());   
    start++;
  } while (result.indexOf(startsWith, ende + 1)>0);
  
    return result;    
 }
  
 protected String readFile(String filename) throws IOException {
   return readFile(filename, "UTF-8");
 }
 protected String readFile(String filename, String encoding) throws IOException {
   return FileUtils.readFile(filename, encoding);
 }
  protected String readString(InputStream input) throws IOException
  {
    return StreamUtils.readStream(input, "UTF-8");   
  }

}