package httpRecorder;

/*
 * Disclaimer:
 * The following source code is sample code created by IBM Corporation.  
 * This sample code is not part of any standard IBM product and is provided 
 * to you solely for the purpose of assisting you in the development of your 
 * applications.  The code is provided 'AS IS', without warranty or condition 
 * of any kind.  IBM shall not be liable for any damages arising out of your 
 * use of the sample code, even if IBM has been advised of the possibility of 
 * such damages.
 */

import httpRecorder.proxy.HttpRequest;
import httpRecorder.proxy.IHttpHeaderName;
import httpRecorder.proxy.ProxyUtil;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Vector;

/**
 * The Component Test documentation describes the format of the 
 * file that can be imported as HTTP test cases.
 */
public class ImportFileWriter
{
	private static final long MIN_THINKTIME = 5000l; //5 seconds
	
	private static class Page
	{
		int number;
		long thinktime;
		HttpRequest pageRequest;
		Vector requests = new Vector();
	}
	
	public static String getFileContent(HttpRequest[] requests)
	{	
		StringBuffer fileContent = new StringBuffer("<pageSet version=\"5.0.0\">");
		fileContent.append(getPages(getPages(requests)));
		fileContent.append("\n").append("</pageSet>");
		
		return fileContent.toString();		
	}
	
	private static Collection getPages(HttpRequest[] requests)
	{
		Vector pages = new Vector();
		if(requests.length == 0)
			return pages;
			
		Vector analysedRequests = analyseRequests(requests);
		
		for (Iterator i = analysedRequests.iterator(); i.hasNext();)
		{
			Vector requestList = (Vector)i.next();
			long previousCreationTime = ((HttpRequest)requestList.get(0)).getCreationTime();
			Page currentPage = null; 
			for (Iterator j = requestList.iterator(); j.hasNext();)
			{
				HttpRequest request = (HttpRequest) j.next();
				if(currentPage == null)
				{
					currentPage = new Page();
					currentPage.number = pages.size() + 1;
					currentPage.pageRequest = request;
					
					pages.add(currentPage);
				}
				else
				{
					currentPage.requests.add(request);
				}
				
				long interval = request.getCreationTime() - previousCreationTime;
				previousCreationTime = request.getCreationTime();
				currentPage.thinktime += interval;			
			}
		}
		
		return pages;	
	}
	
	private static StringBuffer getPages(Collection pages)
	{
		StringBuffer sb = new StringBuffer();
		for(Iterator pageIterator = pages.iterator(); pageIterator.hasNext();)
		{
			Page page = (Page)pageIterator.next();
			
			sb.append("\n\t<page");
			sb.append(ProxyUtil.xmlAttribute("ident", Integer.toString(page.number)));
			if(page.thinktime >= MIN_THINKTIME)
			{
				if(page.number > 1)
					sb.append(ProxyUtil.xmlAttribute("thinktime", Long.toString(page.thinktime)));
			}
			sb.append(">");
			
			sb.append("\n").append(page.pageRequest.toString(2, ProxyUtil.xmlAttribute("requestType", "page").toString()));
			for (Iterator requestIterator = page.requests.iterator(); requestIterator.hasNext();)
			{
				HttpRequest request = (HttpRequest)requestIterator.next();
				sb.append("\n").append(request.toString(2, ProxyUtil.xmlAttribute("requestType", "element").toString()));
			}
			
			sb.append("\n\t</page>");
		}
		
		return sb;
	}
	
	private static boolean isPage(String absolutePath)
	{
		String extension = getFileExtension(absolutePath);
		if((extension == null) || (extension.length() > 5))
			return true;
			
		return
			extension.endsWith("html")
			||extension.endsWith("htm")
			||extension.endsWith("xml")
			||extension.endsWith("txt")
			||extension.endsWith("pdf")
			||extension.endsWith("jsp")
			||extension.endsWith("asp")
			||extension.endsWith("svg");
	}
	
	private static String getFileExtension(String file)
	{
		if(file == null)
			return null;
			
		int index = file.lastIndexOf(".");
		if(index < 0)
			return null;
		
		if(index == (file.length()-1))
			return "";
				
		return file.substring(index+1);
  	}
  	
  	private static Vector analyseRequests(HttpRequest[] requests)
  	{
		Arrays.sort(requests, new Comparator()
		{
			public int compare(Object o1, Object o2)
			{
				HttpRequest request1 = (HttpRequest)o1;
				HttpRequest request2 = (HttpRequest)o2;
				
				if(request1 == null)
				{
					if(request2 == null)
						return 0;
					return 1;
				}

				if(request2 == null)
					return -1;
				
				if((request1 == request2) || (request1.equals(request2)))
					return 0;
				
				if(request1.getCreationTime() == request2.getCreationTime())
					return 0;
				
				return (request1.getCreationTime() < request2.getCreationTime())?-1:1;
			}

			public boolean equals(Object obj)
			{
				return (compare(this, obj) == 0);
			}
		});
		
		Vector analisedRequests = new Vector();
		Hashtable requestByReferer = new Hashtable();
		for(int i = 0; i < requests.length; i++)
		{
			String referer = getReferer(requests[i]);
			Vector requestList = (Vector)requestByReferer.get(referer);
			if(requestList == null)
			{
				requestList = new Vector();
				requestByReferer.put(referer, requestList);
				analisedRequests.add(requestList);
			}
			requestList.add(requests[i]);
		}
		
		return analisedRequests;
  	}
  	
  	private static String getReferer(HttpRequest request)
  	{
  		String value = request.getHeaderValue(IHttpHeaderName.REFERER);
  		if(value != null)
  			return value;
  			
  		return "null referer for HttpRequest " + request.hashCode();
  	}
}