package org.bench4q.agent.test.scenario.utils;

import static org.junit.Assert.*;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;

import org.apache.commons.httpclient.NameValuePair;
import org.bench4q.agent.plugin.basic.http.HttpPlugin;
import org.bench4q.agent.utils.ParameterParser;
import org.bench4q.agent.utils.types.Table;
import org.bench4q.share.helper.TestHelper;
import org.junit.Test;

public class Test_ParameterParser {
	private String testcase = " _nacc=yeah ;_nvid=525d29a534e918cbf04ea7159706a93d;_nvtm=0;_nvsf=0;_nvfi=1;_nlag=zh-cn;_nlmf=1389570024;_nres=1440x900;_nscd=32-bit;_nstm=0;";
	private String testHeaders = "header=Content-Type|value=application/x-www-form-urlencoded|;header=Content-Length|value=63|;header=Accept|value=text/html,application/xhtml+xml,application/xml|;";
	private String testheaderWithUpperCase = "HEADER=Content-Type|Value=application/x-www-form-urlencoded|;header=Content-Length|value=63|;header=Accept|value=text/html,application/xhtml+xml,application/xml|;";
	private static final String TESTCASE1_CONTAIN_SEPARATOR = "header=accept|value=asdfasdf\\|;|;";
	private static final String testcase2 = "header=accept|value=fafsd|;varName=abc|varValue=234|;";

	private String testcaseWithEscapes = "varName=ticket|varExpression=\"ticket\":\\s*?\"\\w+\",|;";
	private List<String> expectedNFField = new ArrayList<String>() {
		private static final long serialVersionUID = 1L;
		{
			add("_nacc=yeah");
			add("_nvid=525d29a534e918cbf04ea7159706a93d");
			add("_nvtm=0");
			add("_nvsf=0");
			add("_nvfi=1");
			add("_nlag=zh-cn");
			add("_nlmf=1389570024");
			add("_nres=1440x900");
			add("_nscd=32-bit");
			add("_nstm=0");
		}
	};

	@Test
	public void testGetNumberOfEscapeCharacter() throws Exception {
		assertEquals(3, "\\\\\\".length());
		assertEquals(2, TestHelper.invokeStaticPrivate(ParameterParser.class,
				"getNumberOfEscapeCharacter", new Class[] { String.class },
				new Object[] { "\\\\" }));
	}

	@Test
	public void testGetRealTokenForContainSeparator() throws Exception {
		List<String> entryList = invokeGetRealTokens(
				Table.ESCAPE_ROW_SEPARATOR, TESTCASE1_CONTAIN_SEPARATOR, true);
		assertEquals(1, entryList.size());
		assertEquals("header=accept|value=asdfasdf|;", entryList.get(0));
	}

	@Test
	public void testGetRealTokenForContainManyEscapse() throws Exception {
		List<String> rowList = invokeGetRealTokens(Table.ESCAPE_ROW_SEPARATOR,
				testcaseWithEscapes, false);
		assertEquals(1, rowList.size());
		assertEquals("varName=ticket|varExpression=\"ticket\":\\s*?\"\\w+\",",
				rowList.get(0));

		final List<String> columnList = invokeGetRealTokens(
				Table.ESCAPE_COLUMN_SEPARATOR, rowList.get(0), false);
		assertEquals(2, columnList.size());
		assertEquals("varName=ticket", columnList.get(0));
		assertEquals("varExpression=\"ticket\":\\s*?\"\\w+\",",
				columnList.get(1));
		@SuppressWarnings("unchecked")
		List<List<String>> result = (List<List<String>>) TestHelper
				.invokeStaticPrivate(Table.class,
						"extractValueFromWellFormedTable",
						new Class<?>[] { List.class },
						new Object[] { new LinkedList<List<String>>() {
							private static final long serialVersionUID = 1L;
							{
								add(columnList);
							}
						} });
		// Table.extractValueFromWellFormedTable(new LinkedList<List<String>>()
		// {
		// private static final long serialVersionUID = 1L;
		// {
		// add(columnList);
		// }
		// });
		assertEquals(1, result.size());
		assertEquals(2, result.get(0).size());
		assertEquals("ticket", result.get(0).get(0));
		assertEquals("\"ticket\":\\s*?\"\\w+\",", result.get(0).get(1));
	}

	@SuppressWarnings("unchecked")
	private List<String> invokeGetRealTokens(String separator, String value,
			boolean toUnescapeSeparator) throws Exception {
		return (List<String>) TestHelper.invokeStaticPrivate(
				ParameterParser.class, "getRealTokens", new Class[] {
						String.class, String.class, boolean.class },
				new Object[] { separator, value, true });
	}

	@Test
	public void testGetRealTokensForMultiSeparator() throws Exception {
		List<String> entryList = invokeGetRealTokens(
				Table.ESCAPE_ROW_SEPARATOR, testcase2, false);
		assertEquals(2, entryList.size());
		assertEquals("header=accept|value=fafsd", entryList.get(0));
		assertEquals("varName=abc|varValue=234", entryList.get(1));
	}

	@Test
	public void testGetTableForSeparator() {
		List<List<String>> resultEntries = buildHeaderTable(
				TESTCASE1_CONTAIN_SEPARATOR).getRealContent();
		assertEquals(1, resultEntries.size());
		assertEquals(2, resultEntries.get(0).size());
		assertEquals("accept", resultEntries.get(0).get(0));
		assertEquals("asdfasdf|;", resultEntries.get(0).get(1));
	}

	@Test
	public void testGetTableForMultipleHeader() {
		List<List<String>> resultEntries = buildHeaderTable(testcase2)
				.getRealContent();
		assertEquals(2, resultEntries.size());
		assertEquals("fafsd", resultEntries.get(0).get(1));
		assertEquals("accept", resultEntries.get(0).get(0));
		assertEquals("234", resultEntries.get(1).get(1));
		assertEquals("abc", resultEntries.get(1).get(0));
	}

	private Table buildHeaderTable(String value) {
		return ParameterParser.buildTable(value, new LinkedList<String>() {
			private static final long serialVersionUID = -6734367739974282326L;
			{
				add("header");
				add("value");
			}
		});
	}

	@Test
	public void testGetTableWithManyEscapse() {
		List<List<String>> resultTable = buildHeaderTable(testcaseWithEscapes)
				.getRealContent();
		assertEquals(1, resultTable.size());
		assertEquals(2, resultTable.get(0).size());
		assertEquals("ticket", resultTable.get(0).get(0));
		assertEquals("\"ticket\":\\s*?\"\\w+\",", resultTable.get(0).get(1));
	}

	@Test
	public void testParseParam() {
		List<String> result = ParameterParser.buildNField(testcase);
		assertEquals(10, result.size());
		for (int i = 0; i < result.size(); i++) {
			assertEquals(result.get(i), expectedNFField.get(i));
			System.out.println(result.get(i));
		}
	}

	@Test
	public void testGetHeadersWithRightCase() throws Exception {
		@SuppressWarnings("unchecked")
		List<NameValuePair> nvPairs = (List<NameValuePair>) TestHelper
				.invokePrivate(new HttpPlugin(UUID.randomUUID().toString()),
						"parseHeaders", new Class[] { String.class },
						new Object[] { testHeaders });

		assertEquals(3, nvPairs.size());
		assertEquals("Content-Type", nvPairs.get(0).getName());
		assertEquals("application/x-www-form-urlencoded", nvPairs.get(0)
				.getValue());
		assertEquals("Content-Length", nvPairs.get(1).getName());
		assertEquals("63", nvPairs.get(1).getValue());
		assertEquals("Accept", nvPairs.get(2).getName());
		assertEquals("text/html,application/xhtml+xml,application/xml", nvPairs
				.get(2).getValue());
	}

	@Test
	public void testGetHeadersWithUpperCase() throws Exception {
		@SuppressWarnings("unchecked")
		List<NameValuePair> nvPairs = (List<NameValuePair>) TestHelper
				.invokePrivate(new HttpPlugin(UUID.randomUUID().toString()),
						"parseHeaders", new Class[] { String.class },
						new Object[] { testheaderWithUpperCase });
		assertEquals(3, nvPairs.size());
		assertEquals("Content-Type", nvPairs.get(0).getName());
		assertEquals("application/x-www-form-urlencoded", nvPairs.get(0)
				.getValue());
		assertEquals("Content-Length", nvPairs.get(1).getName());
		assertEquals("63", nvPairs.get(1).getValue());
		assertEquals("Accept", nvPairs.get(2).getName());
		assertEquals("text/html,application/xhtml+xml,application/xml", nvPairs
				.get(2).getValue());
	}

	@Test
	public void testParseResponseVariables() {

	}

	@Test
	public void testParseNFields() {
		List<String> result = ParameterParser
				.buildNField("file;ScenarioParameters\\\\param1.txt;0;sequence;\\;;~;2");
		assertEquals(7, result.size());
		assertEquals(";", result.get(4));
	}
}
