package test.lasttest;

import java.io.OutputStream;
import java.net.URL;
import java.util.Vector;

import javax.xml.namespace.QName;
import javax.xml.rpc.Call;
import javax.xml.rpc.Service;
import javax.xml.rpc.ServiceFactory;

import org.apache.axis.message.SOAPBodyElement;
import org.w3c.dom.Element;

import at.gv.egovernment.moa.id.proxy.builder.SAMLRequestBuilder;
import at.gv.egovernment.moa.id.util.AxisSecureSocketFactory;
import at.gv.egovernment.moa.util.FileUtils;
import at.gv.egovernment.moa.util.StreamUtils;
import at.gv.egovernment.moa.util.URLDecoder;
import at.gv.egovernment.moa.util.URLEncoder;
import com.sun.net.ssl.HttpsURLConnection;

/**
 * @author Stefan Knirsch
 * @version $Id$
 * 
 */
public class TestThread extends Thread {
  private LasttestClient parent = null;
  private int turn_no;
  private Dispatcher disp = null;
  
  public TestThread( LasttestClient parent, int durchlauf_nr) {
    turn_no = durchlauf_nr;
    this.parent = parent;
 
  }

  protected Element doCall(Element request, String server) throws Exception {

    /*    QName serviceName = new QName("GetAuthenticationData");
    
        String endPoint = server + "services/GetAuthenticationData";
        Service service = ServiceFactory.newInstance().createService(serviceName);
        Call call = service.createCall();
        SOAPBodyElement body = new SOAPBodyElement(request);
        SOAPBodyElement[] params = new SOAPBodyElement[] { body };
        Vector responses;
        SOAPBodyElement response;
        
        
        System.out.println(DOMUtils.serializeNode(body.getAsDOM()));
        call.setTargetEndpointAddress(endPoint);
        System.out.println("Rufe WS auf: " + endPoint);
        responses = (Vector) call.invoke(params);
        System.out.println("WS aufgerufen.");
        response = (SOAPBodyElement) responses.get(0);
        System.out.println(DOMUtils.serializeNode(response.getAsDOM()));
        return response.getAsDOM();*/

    QName serviceName = new QName("GetAuthenticationData");
    String endPoint = server + "services/GetAuthenticationData";
    Service service = ServiceFactory.newInstance().createService(serviceName);
    Call call = service.createCall();

    System.setProperty("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol");
    System.setProperty("javax.net.ssl.trustStore", "C:/Programme/ApacheGroup/abnahme/server.keystore");
    System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
    SOAPBodyElement body = new SOAPBodyElement(request);
    SOAPBodyElement[] params = new SOAPBodyElement[] { body };
    Vector responses;
    SOAPBodyElement response;

    call.setTargetEndpointAddress(endPoint);
    responses = (Vector) call.invoke(params);
    response = (SOAPBodyElement) responses.get(0);
    return response.getAsDOM();
  }

  public boolean doRequest(int turnNo) throws Exception {    
    long start = System.currentTimeMillis();
    
      try {
        LasttestClient.Log.write(("Starte Durchlauf " + turnNo + "\n").getBytes());
      }
      catch (Exception e) {}

      System.out.println("Starte Durchlauf " + turnNo);
    // Anmelden
    String URL = getURL(LasttestClient.MOA_AUTH_SERVER, "gb", "http://10.16.126.28:9080/moa-id-proxy/");
    HttpsURLConnection conn = giveConnection(URL, "GET");
    conn.connect();
    String result = new String(StreamUtils.readStream(conn.getInputStream()));
    /*
     *  FOR DEBUG ONLY
     */
    //    System.out.println(URL);
    //  System.out.println(result);    
    //----------------

    String MOASessionID = parseSessionIDFromForm(result);
    conn.disconnect();

    URL = parseDataURL(result);
    // Verify Identity Link
    conn = giveConnection(URL, "POST");
    conn.setRequestProperty("Content-type", "application/x-www-form-urlencoded");
    String infoboxReadResponse = readXmldata("InfoboxReadResponse.xml");
    OutputStream out = conn.getOutputStream();
    out.write(new String("XMLResponse=" + URLEncoder.encode(infoboxReadResponse, "UTF-8")).getBytes());
    out.flush();
    out.close();
    conn.connect();

    /*
     *  FOR DEBUG ONLY
     */
    // System.out.println(URL);
    // System.out.println(new String(StreamUtils.readStream(conn.getInputStream())));    
    //----------------

    String redirectLoc = conn.getHeaderField("Location");
    conn.disconnect();
    //Verify Auth Block
    conn = giveConnection(redirectLoc, "POST");
    String createXMLSignatureResponse = URLEncoder.encode(readXmldata("CreateXMLSignatureResponse.xml"), "UTF-8");
    out = conn.getOutputStream();
    out.write(("XMLResponse=" + createXMLSignatureResponse).getBytes("UTF-8"));
    out.flush();
    out.close();
    conn.connect();
    redirectLoc = conn.getHeaderField("Location");

    /*
     *  FOR DEBUG ONLY
     */
    // System.out.println(redirectLoc);
    //    System.out.println(new String(StreamUtils.readStream(conn.getInputStream())));    
    //----------------
    String samlArtifact = parseSamlArtifact(redirectLoc);

    //    System.out.println("SamlArtifact: " + samlArtifact);

    AxisSecureSocketFactory.initialize(conn.getSSLSocketFactory());
    conn.disconnect();

    conn = null;

    SAMLRequestBuilder srb = new SAMLRequestBuilder();

    doCall(srb.build(MOASessionID, URLDecoder.decode(samlArtifact, "UTF-8")), LasttestClient.MOA_AUTH_SERVER);
    //  writeXmldata("GetAuthenticationDataWebServiceResponse.xml", result.getBytes("UTF-8"));

    long end = System.currentTimeMillis();    
    long diff = end - start;
    parent.sum +=diff;
    if (parent.max < diff) {
      parent.max = diff;
    }
    if (parent.min > diff) {
      parent.min = diff;
    }
    if (turnNo>0) {
    long totalmem = Runtime.getRuntime().totalMemory();
    long freemem = Runtime.getRuntime().freeMemory();     
    try {
      LasttestClient.Log.write(new String("Ende Durchlauf: " + turnNo + "   ==>   Dauer:" + diff + "    Schnitt: " + (parent.sum/turnNo/2) + "     Total-Mem: " + totalmem + "     Free-Mem: " + freemem +  "\n").getBytes());              
      LasttestClient.Log.flush();
      }
      catch (Exception e) {}        
    System.out.println(new String("Ende Durchlauf: " + turnNo + "   ==>   Dauer:" + diff + "    Schnitt: " + (parent.sum/turnNo/2) + "     Total-Mem: " + totalmem + "     Free-Mem: " + freemem));
    }
    return true;

  }

  public String getSubString(String input, String startsWith, String endsWith) {
    return input.substring(input.indexOf(startsWith) + startsWith.length(), input.indexOf(endsWith, input.indexOf(startsWith) + startsWith.length()));
  }

  public String getURL(String authURL, String target, String oaURL) {
    return authURL + "StartAuthentication?Target=" + target + "&OA=" + oaURL;
  }

  public HttpsURLConnection giveConnection(String targetURL, String requestMethod) throws Exception {
    HttpsURLConnection conn = (HttpsURLConnection) new URL(targetURL).openConnection();
    conn.setRequestMethod(requestMethod);
    conn.setDoInput(true);
    conn.setDoOutput(true);
    conn.setUseCaches(false);
    conn.setAllowUserInteraction(false);
    conn.setHostnameVerifier(new HostnameVerifierHack());
    return conn;
  }

  public 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;
  }

  public String parseDataURL(String input) {
    return getSubString(input.substring(input.indexOf("DataURL"), input.length()), "value=\"", "\"");
  }

  public String parseSamlArtifact(String input) {
//    System.out.println(input);
    return getSubString(input + "@@@", "SAMLArtifact=", "@@@");
  }

  public String parseSessionIDFromForm(String htmlForm) {
    String parName = "MOASessionID=";
    int i1 = htmlForm.indexOf(parName) + parName.length();
    int i2 = htmlForm.indexOf("\"", i1);
    return htmlForm.substring(i1, i2);
  }

  public String readXmldata(String filename) throws Exception {

    return FileUtils.readFile(LasttestClient.TESTDATA_ROOT + "xmldata/L000/" + filename, "UTF-8");
  }

  /**
   * @see java.lang.Runnable#run()
   */
  public void run() {
    parent.thread_counter++;

    try {
      if (!doRequest(turn_no)) {
        parent.error_count++;
      }
    }
    catch (Exception e) {
      e.printStackTrace();
      parent.error_count++;
    }
    parent.thread_counter--;
  }

}