package testclient;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Date;


/**
 * @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.
 */
public class LasttestClient {
	
	
	public int max_thread_count = 300;
	public int thread_counter = 0;
	public int error_count = 0;
	public int turns = 0;
	
	public long max = 0;
	public long min = Long.MAX_VALUE;
	
	public PrintStream Log = null;
		
	public boolean stop = false;
	
	private String readFile(String filename) throws Exception 
	{
		RandomAccessFile raf = new RandomAccessFile(filename, "r");
		if (raf.length() > Integer.MAX_VALUE)
			throw new IOException("file too big to fit in byte array.");
		
		byte[] result = new byte[(int) raf.length()];
				
		raf.read(result);
		
		return new String(result);

	}
	

	
	public String buildRequest(String filename) throws Exception
	{
		String data = readFile(filename);
		int index = data.indexOf(">");
		
		String xml_head = data.substring(0,index+1);
		data = data.substring(index+1);
		//Log.println("Data2:\n"+data);
		
		data = 
		xml_head +
		"<soap:Envelope "+
		"xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\" "+
		"soap:encodingStyle=\"http://www.w3.org/2001/12/soap-encoding\"> "+
		"<soap:Body> "+
		data +
		"</soap:Body>"+
		"</soap:Envelope>";
		
		if(data.indexOf("10.16.46.109")!=-1)
			data = replaceString(data,"10.16.46.109","127.0.0.1");
		
		System.out.println("Request:"+data);
		
		return data;
		
	}
	
	public String buildEndpoint(String request,String server)
	{
		String ep = null;
		if(request.indexOf("<Create")!=-1) ep = server + "moa-spss/services/SignatureCreation";
		else ep = server + "moa-spss/services/SignatureVerification";
		return ep;
	}

	public void startTest(String filename,String server,int req_per_second,int turns) throws Exception
	{
		this.turns = turns;
		String request = buildRequest(filename);
		String ep = buildEndpoint(request,server);
		
		boolean result = doTestRequest(request,ep);
		
		if(result)
		{
			System.out.println("TestRequest OK. Lasttest wird gestartet.");
			Dispatcher dp = new Dispatcher(this,request,ep,req_per_second,turns);
			dp.start();
			while(!stop)
			{
				System.out.println("Checking Stop Condition ...(Running "+thread_counter+", Min "+(min)+", Max "+(max)+", "+new Date(System.currentTimeMillis())+")");
				Thread.sleep(3000);
			}
			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(String request,String endpoint) throws Exception
	{
		HttpURLConnection urlc = (HttpURLConnection)(new URL(endpoint)).openConnection();
		urlc.setDoInput(true);
		urlc.setDoOutput(true);
		urlc.setRequestProperty("SOAPAction","");
		BufferedWriter ow = new BufferedWriter(new OutputStreamWriter(urlc.getOutputStream()));
		ow.write(request);
		ow.flush();
		
		int code = 0;
		try {
			code = urlc.getResponseCode();
		}
		catch(IOException ioe)
		{
			ow.close();
			urlc.disconnect();
			return false;
		}
		BufferedReader iw = new BufferedReader(new InputStreamReader(urlc.getInputStream()));
		while(iw.readLine()!=null) {}
		ow.close();
		
		if(code==500)
		{
			return false;
		}
		else
		{					
			BufferedReader br = new BufferedReader(new InputStreamReader(urlc.getInputStream()));
			StringBuffer response = new StringBuffer();
			String line = null;
			while((line = br.readLine()) != null)
			{
				response.append(line);
			}
			
			iw.close();
			urlc.disconnect();
			
			String resp = response.toString();
			
			int pos = resp.indexOf("ErrorCode>");
			if(pos==-1)
			{
				return true;
			}
			else
			{
				return false;
			}			
		}					
		
	}
	
	private 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 
	{
		int sek = 0;
		int turns = 0;
		
		if(args.length!=4)
		{
			System.out.println("Parameteranzahl falsch. Bitte verwenden Sie die Syntax <Requestdatei><ServerURL><Request_pro_Sekunde(Zahl)><Anzahl_der_Durchl�ufe(Zahl oder INF)>");
			return;
		}
		
		try {
			sek = Integer.parseInt(args[2]);
			if(args[3].equals("INF"))
			{
				turns = 0;
			}
			else
				turns = Integer.parseInt(args[3]);
		}	
		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("Requestdatei:         "+args[0]);
		System.out.println("ServerURL:            "+args[1]);
		System.out.println("Requests pro Sekunde: "+sek);
		System.out.println("Durchl�ufe:           "+(turns==0?"INF":turns+""));
		
		
		LasttestClient lc = new LasttestClient();
		//lc.startTest("data/CX0/TestGeneratorCX0.001.Req.xml","http://161.106.2.255:8080/",10,1000);
		lc.startTest(args[0],args[1],sek,turns);
	}
}

class Dispatcher extends Thread
{
	private String request = null;
	private String endpoint = null;
	private LasttestClient parent = null;
	private int max;
	private int turns;
	public Dispatcher(LasttestClient parent,String request,String endpoint,int max,int turns)
	{
		this.request = request;
		this.endpoint = endpoint;
		this.parent = parent;
		this.max = max;
		this.turns = turns;
	}
	
	public void run()
	{
		this.setPriority(Thread.NORM_PRIORITY+1);
		System.out.println("Dispatcher wird gestartet...");
		TestThread[] old_reqs = buildRequests();
		for(int turn_counter=0;turns==0?true:(turn_counter<turns);turn_counter++)
		{
			System.out.println("Durchlauf "+turn_counter);
			if(turns==0) turn_counter--;
			TestThread[] reqs = buildRequests();
			for(int counter=0;counter<max;counter++)
			{
				old_reqs[counter].start();
			}	
			old_reqs = reqs;
			try {
				Thread.sleep(1000);
			}
			catch(Exception e) { e.printStackTrace(); }
		}
		parent.stop = true;
	}
	
	public TestThread[] buildRequests()
	{
		TestThread[] ret = new TestThread[max];
		for(int counter=0;counter<max;counter++)
		{
			ret[counter] = new TestThread(parent,request,endpoint);
		}	
		return ret;	
	}
}

class TestThread extends Thread
{
	private String request = null;
	private String endpoint = null;
	private LasttestClient parent = null;
	public TestThread(LasttestClient parent,String request,String endpoint)
	{
		this.request = request;
		this.endpoint = endpoint;
		this.parent = parent;
		
	}
	

	/**
	 * @see java.lang.Runnable#run()
	 */
	public void run() {
		parent.thread_counter++;	
		
		try {
			if(!doRequest())
			{
				parent.error_count++;
			}
		}
		catch(Exception e)
		{
			e.printStackTrace();
			parent.error_count++;
		}		
		parent.thread_counter--;
	}
	
	public boolean doRequest() throws Exception
	{
		long start = System.currentTimeMillis();
		HttpURLConnection urlc = (HttpURLConnection)(new URL(endpoint)).openConnection();
		urlc.setDoInput(true);
		urlc.setDoOutput(true);
		urlc.setAllowUserInteraction(false);
		urlc.setUseCaches(false);
    HttpURLConnection.setFollowRedirects(false);
		urlc.setRequestProperty("SOAPAction","");		

		
		BufferedWriter ow = new BufferedWriter(new OutputStreamWriter(urlc.getOutputStream()));
		ow.write(request);
		ow.flush();
		
		int code = 0;
		/*try {
			code = urlc.getResponseCode();
		}
		catch(IOException ioe)
		{
			ow.close();
			urlc.disconnect();
			return false;
		}*/
		ow.close();
		BufferedReader iw = new BufferedReader(new InputStreamReader(urlc.getInputStream()));
		while(iw.readLine()!=null) {}
		
		if(code==500)
		{
			return false;
		}
		else
		{					
			BufferedReader br = new BufferedReader(new InputStreamReader(urlc.getInputStream()));
			StringBuffer response = new StringBuffer();
			String line = null;
			while((line = br.readLine()) != null)
			{
				response.append(line);
			}
			
			iw.close();
			urlc.disconnect();
			long end = System.currentTimeMillis();
			
			String resp = response.toString();
			
			int pos = resp.indexOf("ErrorCode>");
			if(pos==-1)
			{
				long diff = end-start;
				if(parent.max<diff)
				{
					parent.max=diff;
				}				
				if(parent.min>diff)
				{
					parent.min=diff;
				}
				return true;
				
			}
			else
			{
				return false;
			}			
		}					
		
	}

}