package org.bench4q.agent.test.plugin;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.httpclient.Cookie;
import org.apache.commons.httpclient.cookie.MalformedCookieException;
import org.apache.commons.io.FileUtils;
import org.bench4q.agent.plugin.basic.PluginReturn;
import org.bench4q.agent.plugin.basic.http.BatchRequest;
import org.bench4q.agent.plugin.basic.http.HttpPlugin;
import org.bench4q.agent.plugin.basic.http.HttpReturn;
import org.bench4q.agent.scenario.Scenario;
import org.bench4q.agent.scenario.engine.VUser;
import org.bench4q.agent.test.TestBase;
import org.bench4q.share.helper.MarshalHelper;
import org.bench4q.share.helper.TestHelper;
import org.bench4q.share.models.agent.RunScenarioModel;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.google.gson.Gson;

import static org.junit.Assert.*;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:application-context.xml" })
public class Test_HttpPlugin extends TestBase {
	private static final int UnAuthorized = 401;
	private HttpPlugin httpPlugin;

	private HttpPlugin getHttpPlugin() {
		return httpPlugin;
	}

	private void setHttpPlugin(HttpPlugin httpPlugin) {
		this.httpPlugin = httpPlugin;
	}

	public Test_HttpPlugin() {
		this.setHttpPlugin(new HttpPlugin(UUID.randomUUID().toString()));
	}

	@Test
	public void testGet() {
		PluginReturn return1 = this.getHttpPlugin().get(
				"http://www.baidu.com/s", "wd=ok", "", "");
		assertTrue(return1.getSuccessCount() > 0);
	}

	@Test
	public void testSessionAndCookie() throws MalformedCookieException,
			IllegalArgumentException {
		String loginPageUrl = "http://124.16.137.203:7080/cloudshare_web/login";
		HttpReturn indexReturn = this
				.getHttpPlugin()
				.get(loginPageUrl,
						"",
						"header=Accept|value=text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8|;",
						null);
		assertEquals(UnAuthorized, indexReturn.getStatusCode());
		assertNotNull(indexReturn.getHeaders());
		logTheCookie("first");

		HttpReturn loginReturn = this
				.getHttpPlugin()
				.post(loginPageUrl,
						null,
						"header=Content-Type|value=application/x-www-form-urlencoded|;header=Content-Length|value=63|;header=Accept|value=text/html,application/xhtml+xml,application/xml|;",
						"username=chentienan12%40otcaix.iscas.ac.cn&password=jingcai2008",
						null, null);
		assertEquals(302, loginReturn.getStatusCode());
		assertNotNull(loginReturn.getHeaders());
		logTheCookie("second");

		HttpReturn homeReturn = this
				.getHttpPlugin()
				.get("http://124.16.137.203:7080/cloudshare_web/home",
						null,
						"header=Accept|value=text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8|;",
						null);
		assertEquals(200, homeReturn.getStatusCode());
		logTheCookie("third");

		HttpReturn ticketReturn = this
				.getHttpPlugin()
				.post("http://124.16.137.203:7080/cloudshare_web/v2/file/ajax/uploadFiles/-1",
						null,
						"header=Accept|value=*/*|;"
								+ "header=Content-Length|value=0|;"
								+ "header=X-Requested-With|value=XMLHttpRequest|;",
						"",
						null,
						"varName=ticket|varExpression=\"ticket\":\\s*?\"\\w+\",|leftBoundry=\"ticket\"\": \"|rightBoundry=\",|;");
		assertEquals(200, ticketReturn.getStatusCode());
		assertNotNull(this.getHttpPlugin().getValue("ticket"));
		System.out.println(this.getHttpPlugin().getValue("ticket"));
	}

	private void logTheCookie(String times) {
		for (Cookie cookie : this.getHttpPlugin().getHttpClient().getState()
				.getCookies()) {
			System.out.println("Cookie from httpState for " + times + " : "
					+ cookie.getName() + " : " + cookie.getValue());
		}
	}

	@Test
	public void testDoExtractResponseVariables() throws Exception {
		String respVarsToSave = "varName=ticket|varExpression=\"ticket\":\\s*?\"\\w+\",|leftBoundry=\"ticket\": \"|rightBoundry=\",|;";
		String responseBodyAsString = "{" + "\n"
				+ "\"ticket\": \"e55de793fc934001b156e97f94ff3eb6\"," + "\n"
				+ "\"parentId\": 3273," + "\n" + "\"expiresIn\": 300000" + "\n"
				+ "}";
		@SuppressWarnings("unchecked")
		Map<String, String> nameValueMap = (Map<String, String>) TestHelper
				.invokePrivate(this.getHttpPlugin(),
						"doExtractResponseVariablesAndSave", new Class<?>[] {
								String.class, String.class }, new Object[] {
								respVarsToSave, responseBodyAsString });
		assertEquals(1, nameValueMap.size());
		assertTrue(nameValueMap.containsKey("ticket"));
		System.out.println(nameValueMap.get("ticket"));
		assertEquals("e55de793fc934001b156e97f94ff3eb6",
				nameValueMap.get("ticket"));
		assertEquals("e55de793fc934001b156e97f94ff3eb6", this.getHttpPlugin()
				.getValue("ticket"));
	}

	@Test
	public void testForElectric() {
		Map<String, String> queryParams = new HashMap<String, String>();
		queryParams
				.put("eleData",
						"DevId:10001_Time:2014051514561_U:220_I:210_Usage:65.3_Sum:11.1");
		HttpReturn result = this.httpPlugin
				.post("http://133.133.133.99:8080/getMeterLog",
						"eleData=DevId:10001_Time:2014051514561_U:220_I:210_Usage:65.3_Sum:11.1;",
						null, null, null, null);
		assertEquals(200, result.getStatusCode());
	}

	@Test
	public void buildAScenario() throws IOException {
		RunScenarioModel scenarioMode = (RunScenarioModel) MarshalHelper
				.tryUnmarshal(RunScenarioModel.class, FileUtils
						.readFileToString(new File(
								"Scripts/httpWithoutTimer.xml")));
		VUser vUser = createVUser(
				Scenario.scenarioBuilderWithCompile(scenarioMode),
				UUID.randomUUID());
		vUser.run();
	}

	@Test
	public void test_BatchRequest() {
		BatchRequest.BatchItem batchItem = buildItem("Get",
				"http://www.baidu.com");
		BatchRequest batchRequest = new BatchRequest();
		batchRequest.setBatchItems(Arrays.asList(batchItem,
				buildItem("Get", "http://www.csdn.net/")));
		String batchItemInJson = new Gson().toJson(batchRequest);
		System.out.println(batchItemInJson);
		List<HttpReturn> returns = this.httpPlugin
				.batchRequest(batchItemInJson);
		for (HttpReturn return1 : returns) {
			System.out.println(return1.getUrl());
			assertEquals(200, return1.getStatusCode());
		}
	}

	private BatchRequest.BatchItem buildItem(String method, String url) {
		BatchRequest.BatchItem batchItem = new BatchRequest.BatchItem();
		batchItem.setMethod(method);
		batchItem.setUrl(url);
		batchItem.setHeaders("");
		batchItem.setQueryParams("");
		batchItem.setBodyContent("");
		batchItem.setBodyparameters("");
		batchItem.setRespVarsToSaveInSession("");
		return batchItem;
	}
}
