package org.bench4q.agent.test.datastatistics;

import static org.junit.Assert.*;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import org.bench4q.agent.datacollector.DataCollector;
import org.bench4q.agent.datacollector.impl.ScenarioResultCollector;
import org.bench4q.agent.datacollector.impl.BehaviorStatusCodeResult;
import org.bench4q.agent.scenario.engine.BehaviorResult;
import org.bench4q.agent.storage.StorageHelper;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class DetailStatisticsTest {
	private DataCollector detailStatistics;

	private DataCollector getDetailStatistics() {
		return detailStatistics;
	}

	private void setDetailStatistics(DataCollector detailStatistics) {
		this.detailStatistics = detailStatistics;
	}

	public DetailStatisticsTest() {
		init();
	}

	private void init() {
		@SuppressWarnings("resource")
		ApplicationContext context = new ClassPathXmlApplicationContext(
				"classpath*:/org/bench4q/agent/config/application-context.xml");
		ScenarioResultCollector agentResultDataCollector = new ScenarioResultCollector(
				UUID.randomUUID());
		agentResultDataCollector.setStorageHelper((StorageHelper) context
				.getBean(StorageHelper.class));
		this.setDetailStatistics(agentResultDataCollector);
	}

	@Test
	public void addZeroTest() {
		for (BehaviorResult behaviorResult : ScenarioStatisticsTest
				.makeBehaviorListWhoseBehaviorIdIsOne(0)) {
			this.getDetailStatistics().add(behaviorResult);
		}

		Object object = this.detailStatistics.getBehaviorBriefStatistics(0);
		assertEquals(null, object);
	}

	@Test
	public void addOneDetailTest() {
		for (BehaviorResult behaviorResult : ScenarioStatisticsTest
				.makeBehaviorListWhoseBehaviorIdIsOne(1)) {
			this.getDetailStatistics().add(behaviorResult);
		}
		Map<Integer, BehaviorStatusCodeResult> map = this.detailStatistics
				.getBehaviorBriefStatistics(1);

		BehaviorStatusCodeResult actualResult = map.get(200);
		assertTrue(actualResult.equals(makeExpectedResultForOne()));
	}

	private BehaviorStatusCodeResult makeExpectedResultForOne() {
		BehaviorStatusCodeResult ret = new BehaviorStatusCodeResult("");
		ret.contentLength = 20;
		ret.count = 1;
		ret.maxResponseTime = 200;
		ret.minResponseTime = 200;
		ret.totalResponseTimeThisTime = 200;
		return ret;
	}

	@Test
	public void addTwoDetailTest() {
		for (BehaviorResult behaviorResult : ScenarioStatisticsTest
				.makeBehaviorListWhoseBehaviorIdIsOne(2)) {
			this.getDetailStatistics().add(behaviorResult);
		}
		Map<Integer, BehaviorStatusCodeResult> map = this.detailStatistics
				.getBehaviorBriefStatistics(1);
		assertTrue(mapEquals(map, makeExpectedMapForTwo()));
	}

	private Map<Integer, BehaviorStatusCodeResult> makeExpectedMapForTwo() {
		Map<Integer, BehaviorStatusCodeResult> ret = new HashMap<Integer, BehaviorStatusCodeResult>();
		ret.put(new Integer(200), buildCodeResult(20, 1, 200, 200, 200));
		ret.put(new Integer(400),
				buildCodeResult(0, 1, Long.MIN_VALUE, Long.MAX_VALUE, 0));
		return ret;
	}

	@Test
	public void addFourDetailTest() {
		for (BehaviorResult behaviorResult : ScenarioStatisticsTest
				.makeBehaviorListWhoseBehaviorIdIsOne(4)) {
			this.getDetailStatistics().add(behaviorResult);
		}
		Map<Integer, BehaviorStatusCodeResult> map = this.detailStatistics
				.getBehaviorBriefStatistics(1);
		assertTrue(mapEquals(map, makeExpectedMapForFour()));

	}

	private Map<Integer, BehaviorStatusCodeResult> makeExpectedMapForFour() {
		Map<Integer, BehaviorStatusCodeResult> ret = new HashMap<Integer, BehaviorStatusCodeResult>();
		ret.put(new Integer(200), buildCodeResult(40, 2, 220, 200, 420));
		ret.put(new Integer(400),
				buildCodeResult(0, 2, Long.MIN_VALUE, Long.MAX_VALUE, 0));
		return ret;
	}

	private BehaviorStatusCodeResult buildCodeResult(long contentLength,
			long count, long maxResponseTime, long minResponseTime,
			long totalResponseTimeThisTime) {
		BehaviorStatusCodeResult ret = new BehaviorStatusCodeResult("");
		ret.contentLength = contentLength;
		ret.count = count;
		ret.maxResponseTime = maxResponseTime;
		ret.minResponseTime = minResponseTime;
		ret.totalResponseTimeThisTime = totalResponseTimeThisTime;
		return ret;
	}

	private boolean mapEquals(Map<Integer, BehaviorStatusCodeResult> mapActual,
			Map<Integer, BehaviorStatusCodeResult> mapExpected) {
		boolean equal = true;
		if (mapActual.size() != mapExpected.size()) {
			return false;
		}
		for (int i : mapActual.keySet()) {
			if (!mapActual.get(i).equals(mapExpected.get(i))) {
				equal = false;
			}
		}
		return equal;
	}

	@Test
	public void addThreeTest() {
		for (BehaviorResult behaviorResult : ScenarioStatisticsTest
				.makeBehaviorListWhoseBehaviorIdIsOne(3)) {
			this.getDetailStatistics().add(behaviorResult);
		}
		Map<Integer, BehaviorStatusCodeResult> mapActual = this
				.getDetailStatistics().getBehaviorBriefStatistics(1);
		assertTrue(mapEquals(mapActual, makeExpectedMapForThree()));
	}

	private Map<Integer, BehaviorStatusCodeResult> makeExpectedMapForThree() {
		Map<Integer, BehaviorStatusCodeResult> retMap = new HashMap<Integer, BehaviorStatusCodeResult>();
		retMap.put(200, buildCodeResult(40, 2, 220, 200, 420));
		retMap.put(400,
				buildCodeResult(0, 1, Long.MIN_VALUE, Long.MAX_VALUE, 0));
		return retMap;
	}
}
