package test.lasttest;

import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.security.Security;
import java.util.Date;

import org.w3c.dom.Element;

import at.gv.egovernment.moa.id.auth.AuthenticationServer;
import at.gv.egovernment.moa.id.config.ConfigurationProvider;
import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
import at.gv.egovernment.moa.id.proxy.builder.SAMLRequestBuilder;
import at.gv.egovernment.moa.util.DOMUtils;
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 Sven
 *
 * To change this generated comment edit the template variable "typecomment":
 * Window>Preferences>Java>Templates.
 * To enable and disable the creation of type comments go to
 * Window>Preferences>Java>Code Generation.
 * 
 * Aufruf: Requestdatei (==null), ServerURL, Anzahl der Requests pro Sekunde, Anzahl der Wiederholungen
 * z.b. "data/CX0/TestGeneratorCX0.001.Req.xml" "http://127.0.0.1:8080/" 5 100
 * 
 * ==> GE�NDERT: ersten 2 Parameter gekillt... nur noch   5 100
 */
public class LasttestClient {

  protected static final String TESTDATA_ROOT = "data/abnahme-test/";
  protected static final String MOA_AUTH_SERVER = "https://localhost:8443/moa-id-auth/";
  protected AuthenticationServer server;

  public int max_thread_count = 300;
  public int thread_counter = 0;
  public int error_count = 0;
  public int turns = 0;
  public long sum = 0;
  public long max = 0;
  public long min = Long.MAX_VALUE;

  public static PrintStream Log = null;
  
  public boolean stop = false;

  public static final String trustStore = "javax.net.ssl.trustStore";
  public static final String trustStorePassword = "javax.net.ssl.trustStorePassword";
  public static final String handler = "java.protocol.handler.pkgs";

  public void startTest(int req_per_second, int turns, int time) throws Exception {
    Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());

    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");

    System.setProperty(ConfigurationProvider.CONFIG_PROPERTY_NAME, TESTDATA_ROOT + "xmldata/L000/Configuration.xml");
    
    AuthConfigurationProvider.reload();

    this.turns = turns;

    boolean result = new TestThread(this,0).doRequest(0);// doTestRequest();    
    if (result) {
      System.out.println("TestRequest OK. Lasttest wird gestartet.");
      sum=0;
      max=0;
      Dispatcher dp = new Dispatcher(this, req_per_second, turns, time, sum);
      dp.start();
      while (!stop) {
            try {
      Log.println(new String(("Checking Stop Condition ...(Running " + thread_counter + ", Min " + (min) + ", Max " + (max) + ", " + new Date(System.currentTimeMillis()) + ")")));              
      Log.flush();
      }
      catch (Exception e) {}

        System.out.println("Checking Stop Condition ...(Running " + thread_counter + ", Min " + (min) + ", Max " + (max) + ", " + new Date(System.currentTimeMillis()) + ")");
        Thread.sleep(10000);
      }
      System.out.println("Fehler:" + error_count + " (Running " + thread_counter + ", Min " + (min) + ", Max " + (max) + ", " + new Date(System.currentTimeMillis()) + ")");
    }
    else {
      System.out.println("TestRequest lieferte einen Fehler. Lasttest wird nicht gestartet.");
    }
  }


  public boolean doTestRequest() throws Exception {
    
    try {

      TestThread tt = new TestThread(null,0);

      // Anmelden
      String URL = tt.getURL(MOA_AUTH_SERVER, "gb", "http://10.16.126.28:9080/moa-id-proxy/");
      HttpsURLConnection conn = tt.giveConnection(URL, "GET");

      conn.connect();
      String result = new String(StreamUtils.readStream(conn.getInputStream()));
      String MOASessionID = tt.parseSessionIDFromForm(result);
      conn.disconnect();

      URL = tt.parseDataURL(result);
      // Verify Identity Link
      conn = tt.giveConnection(URL, "POST");
      conn.setRequestProperty("Content-type", "application/x-www-form-urlencoded");
      String infoboxReadResponse = tt.readXmldata("InfoboxReadResponse.xml");
      OutputStream out = conn.getOutputStream();
      out.write(new String("XMLResponse=" + URLEncoder.encode(infoboxReadResponse, "UTF-8")).getBytes());
      out.flush();
      out.close();
      conn.connect();
      String redirectLoc = conn.getHeaderField("Location");
      conn.disconnect();
      //Verify Auth Block
      conn = tt.giveConnection(redirectLoc, "POST");
      String createXMLSignatureResponse = URLEncoder.encode(tt.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");
      String samlArtifact = tt.parseSamlArtifact(redirectLoc);
      System.out.println("SamlArtifact: " + samlArtifact);
 
      conn.disconnect();

      conn = null;

      SAMLRequestBuilder srb = new SAMLRequestBuilder();

      Element erg = tt.doCall(srb.build(MOASessionID, URLDecoder.decode(samlArtifact, "UTF-8")),MOA_AUTH_SERVER);
      result = DOMUtils.serializeNode(erg);
      if (result.indexOf("saml:Assertion")<0)
      {
        System.err.println("Falsche Antwort vom Webservice:\n" + result);
        throw new Exception("Falsche Antwort vom Webservice");
        
      }
    }
    catch (Exception e) {
      System.err.println("------ FEHLER IN LASTTEST :" + e.getLocalizedMessage());
      throw e;
    }

    return true;

  }

  public String replaceString(String input, String oldPart, String newPart) throws Exception {
    String erg = null;

    //First Part
    erg = input.substring(0, input.indexOf(oldPart));
    //Insert new Part
    erg += newPart;

    //insert REST
    erg += input.substring(input.indexOf(oldPart) + oldPart.length(), input.length());

    return erg;
  }

  public static void main(String[] args) throws Exception {
    Log = new PrintStream(new FileOutputStream("C:/Lasttest.log"));
    int time = 0;
    int sek = 0;
    int turns = 0;

    if (args.length != 3) {
      System.out.println("Parameteranzahl falsch. Bitte verwenden Sie die Syntax <Request_pro_Zeiteinheit(Zahl)> <Anzahl_der_Durchl�ufe(Zahl oder INF)> <Zeit_zwischen_Aufrufen_in_ms(Zahl)>");
      return;
    }

    try {
      sek = Integer.parseInt(args[0]);
      time = Integer.parseInt(args[2]);
      if (args[1].equals("INF")) {
        turns = 0;
      }
      else
        turns = Integer.parseInt(args[1]);
    }
    catch (NumberFormatException e) {
      System.out.println("Einer der Parameter (Requestanzahl oder Testanzahl) ist keine Zahl !");
      return;
    }

    System.out.println("Starte Lastest mit folgenden Parametern ...");
    System.out.println("ServerURL:            " + MOA_AUTH_SERVER);
    double reqPerSek = sek*1000;
    System.out.println("Requests pro Sekunde: " + reqPerSek/time);
    System.out.println("Durchl�ufe:           " + (turns == 0 ? "INF" : turns + ""));

    Log.println("Starte Lastest mit folgenden Parametern ...");
    Log.println("ServerURL:            " + MOA_AUTH_SERVER);
    Log.println("Requests pro Sekunde: " + reqPerSek / time);
    Log.println("Durchl�ufe:           " + (turns == 0 ? "INF" : turns + ""));


    try {
      LasttestClient lc = new LasttestClient();
      //lc.startTest("data/CX0/TestGeneratorCX0.001.Req.xml","http://161.106.2.255:8080/",10,1000);
      lc.startTest(sek, turns, time);
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
}