package org.bench4q.master.domain.valueobject.datastatistics;

import java.util.Date;

import org.bench4q.share.models.agent.statistics.AgentBriefStatusModel;
import org.bench4q.share.models.agent.statistics.DataStatisticsModel;
import org.bench4q.share.models.master.statistics.ScriptBriefResultModel;

public class ScriptBriefStatistics extends ScriptStatistics {
	private long totalFailCountThisTime;
	private long totalSuccessCountThisTime;
	private long totalSquareResponseTime;
	private long totalFailThroughputThisTime;
	private long totalSuccessThroughputThisTime;
	private long minResponseTimeThisTime;
	private long maxResponseTimeThisTime;
	private long totalResponseTimeThisTime;
	private long totalFailCountFromBegin;
	private long totalSuccessCountFromBegin;

	private long totalElapsedTime;
	private long activeVUserCountThisTime;
	private long effectiveCount;

	private ScriptBriefResultModel lastValidBriefResultModel;

	private void setTotalFailCountThisTime(long totalFailCountThisTime) {
		this.totalFailCountThisTime = totalFailCountThisTime;
	}

	private void setTotalSuccessCountThisTime(long totalSuccessCountThisTime) {
		this.totalSuccessCountThisTime = totalSuccessCountThisTime;
	}

	private void setTotalSquareResponseTime(long totalSquareResponseTime) {
		this.totalSquareResponseTime = totalSquareResponseTime;
	}

	private void setTotalFailThroughputThisTime(long totalFailThroughputThisTime) {
		this.totalFailThroughputThisTime = totalFailThroughputThisTime;
	}

	private void setTotalSuccessThroughputThisTime(
			long totalSuccessThroughputThisTime) {
		this.totalSuccessThroughputThisTime = totalSuccessThroughputThisTime;
	}

	private void setMinResponseTimeThisTime(long minResponseTimeThisTime) {
		this.minResponseTimeThisTime = minResponseTimeThisTime;
	}

	private void setMaxResponseTimeThisTime(long maxResponseTimeThisTime) {
		this.maxResponseTimeThisTime = maxResponseTimeThisTime;
	}

	private void setTotalResponseTimeThisTime(long totalResponseTimeThisTime) {
		this.totalResponseTimeThisTime = totalResponseTimeThisTime;
	}

	private void setTotalFailCountFromBegin(long totalFailCountFromBegin) {
		this.totalFailCountFromBegin = totalFailCountFromBegin;
	}

	private void setTotalSuccessCoutFromBegin(long totalSuccessCoutFromBegin) {
		this.totalSuccessCountFromBegin = totalSuccessCoutFromBegin;
	}

	private void setTotalElapsedTime(long totalElapsedTime) {
		this.totalElapsedTime = totalElapsedTime;
	}

	private void setActiveVUserCountThisTime(long activeVUserCountThisTime) {
		this.activeVUserCountThisTime = activeVUserCountThisTime;
	}

	private void setEffectiveCounte(long effetiveCount) {
		this.effectiveCount = effetiveCount;
	}

	private ScriptBriefResultModel getLastValidBriefResultModel() {
		return lastValidBriefResultModel;
	}

	private void setLastValidBriefResultModel(
			ScriptBriefResultModel lastValidBriefResultModel) {
		this.lastValidBriefResultModel = lastValidBriefResultModel;
	}

	public ScriptBriefStatistics() {
		reset();
		initLastValidBriefResultModel();
	}

	private void reset() {
		this.setTotalFailCountFromBegin(0);
		this.setTotalFailCountThisTime(0);
		this.setTotalFailThroughputThisTime(0);
		this.setTotalResponseTimeThisTime(0);
		this.setTotalSquareResponseTime(0);
		this.setTotalSuccessCountThisTime(0);
		this.setTotalSuccessCoutFromBegin(0);
		this.setTotalSuccessThroughputThisTime(0);
		this.setTotalElapsedTime(0);
		this.setEffectiveCounte(0);
		this.setMaxResponseTimeThisTime(Long.MIN_VALUE);
		this.setMinResponseTimeThisTime(Long.MAX_VALUE);
		this.setActiveVUserCountThisTime(0);
	}

	private void initLastValidBriefResultModel() {
		ScriptBriefResultModel initBriefModel = new ScriptBriefResultModel();
		initBriefModel.setAverageElapsedTime(0);
		initBriefModel.setAverageResponseTime(0);
		initBriefModel.setFailRateThisTime(0);
		initBriefModel.setFailThroughputThisTime(0);
		initBriefModel.setFinished(false);
		initBriefModel.setMaxResponseTime(0);
		initBriefModel.setMinResponseTime(0);
		initBriefModel.setPlanedRunningTime(0);
		initBriefModel.setResponseTimeDeviationThisTime(0);
		initBriefModel.setSuccessThroughputThisTime(0);
		initBriefModel.setTotalFailCountFromBegin(0);
		initBriefModel.setTotalSuccessCountFromBegin(0);
		this.setLastValidBriefResultModel(initBriefModel);
	}

	public void add(DataStatisticsModel dataUnit) {
		if (!(dataUnit instanceof AgentBriefStatusModel)) {
			return;
		}
		add((AgentBriefStatusModel) dataUnit);
	}

	private void add(AgentBriefStatusModel briefModel) {
		if (briefModel == null) {
			return;
		}
		this.effectiveCount++;
		if (briefModel.getMaxResponseTime() > this.maxResponseTimeThisTime) {
			this.setMaxResponseTimeThisTime(briefModel.getMaxResponseTime());
		}
		if (briefModel.getMinResponseTime() < this.minResponseTimeThisTime) {
			this.setMinResponseTimeThisTime(briefModel.getMinResponseTime());
		}
		this.totalFailCountFromBegin += briefModel.getFailCountFromBegin();
		this.totalFailCountThisTime += briefModel.getFailCountThisTime();
		this.totalFailThroughputThisTime += briefModel
				.getFailThroughputThisTime();
		this.totalResponseTimeThisTime += briefModel
				.getTotalResponseTimeThisTime();
		this.totalSquareResponseTime += briefModel
				.getTotalSqureResponseTimeThisTime();
		this.totalSuccessCountThisTime += briefModel.getSuccessCountThisTime();
		this.totalSuccessCountFromBegin += briefModel
				.getSuccessCountFromBegin();
		this.totalSuccessThroughputThisTime += briefModel
				.getSuccessThroughputThisTime();
		this.activeVUserCountThisTime += briefModel.getvUserCount();
	}

	public ScriptBriefResultModel getStatistics() {
		ScriptBriefResultModel result = new ScriptBriefResultModel();
		long averageResponseTime = 0;
		if (this.totalSuccessCountThisTime == 0) {
			result.setAverageResponseTime(0);
			result.setMaxResponseTime(0);
			result.setMinResponseTime(0);
			result.setResponseTimeDeviationThisTime(0);
			if (this.totalFailCountThisTime == 0) {
				result.setFailRateThisTime(0);
			} else {
				result.setFailRateThisTime(100);
			}
		} else {
			averageResponseTime = this.totalResponseTimeThisTime
					/ this.totalSuccessCountThisTime;
			result.setAverageResponseTime(averageResponseTime);
			result.setMaxResponseTime(this.maxResponseTimeThisTime);
			result.setMinResponseTime(this.minResponseTimeThisTime);
			result.setResponseTimeDeviationThisTime(Math.round(Math
					.sqrt(this.totalSquareResponseTime
							/ this.totalSuccessCountThisTime
							- averageResponseTime * averageResponseTime)));
			result.setFailRateThisTime(this.totalFailCountThisTime
					* 100
					/ (this.totalFailCountThisTime + this.totalSuccessCountThisTime));
		}
		result.setFailThroughputThisTime(this.totalFailThroughputThisTime);
		result.setSuccessThroughputThisTime(this.totalSuccessThroughputThisTime);
		result.setTotalFailCountFromBegin(this.totalFailCountFromBegin);
		result.setTotalSuccessCountFromBegin(this.totalSuccessCountFromBegin);
		if (this.effectiveCount == 0) {
			result.setAverageElapsedTime(0);
		} else {
			result.setAverageElapsedTime(this.totalElapsedTime
					/ this.effectiveCount);
		}
		result = dealWithInvalidSamplePoint(result);
		result.setSamplingTime(new Date());
		result.setvUserCount(this.activeVUserCountThisTime);
		reset();
		return result;
	}

	private ScriptBriefResultModel dealWithInvalidSamplePoint(
			ScriptBriefResultModel inputModel) {
		if (this.totalSuccessCountFromBegin == 0
				&& this.totalFailCountFromBegin == 0) {
			return this.getLastValidBriefResultModel();
		}
		this.setLastValidBriefResultModel(inputModel);
		return inputModel;
	}
}
