package org.bench4q.web.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;
import org.bench4q.share.models.agent.BehaviorBriefModel;
import org.bench4q.share.models.agent.BehaviorStatusCodeResultModel;
import org.bench4q.share.models.agent.ScriptFilterOptionsModel;
import org.bench4q.share.models.master.MonitorModel;
import org.bench4q.share.models.master.RunningScriptModel;
import org.bench4q.share.models.master.ScriptHandleModel;
import org.bench4q.share.models.master.TestPlanModel;
import org.bench4q.share.models.master.TestPlanResultModel;
import org.bench4q.share.models.master.TestPlanScriptBriefResultModel;
import org.bench4q.share.models.master.TestScriptConfig;
import org.bench4q.share.models.master.statistics.ScriptBehaviorsBriefModel;
import org.bench4q.share.models.master.statistics.ScriptBriefResultModel;
import org.bench4q.web.masterMessager.TestPlanMessager;
import org.bench4q.web.model.ResultModel;
import org.bench4q.web.model.TestPlanRequestModel;
import org.bench4q.web.model.WebScriptModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class TestPlanService {
	private TestPlanMessager testPlanMessager;

	public TestPlanMessager getTestPlanMessager() {
		return testPlanMessager;
	}

	@Autowired
	public void setTestPlanMessager(TestPlanMessager testPlanMessager) {
		this.testPlanMessager = testPlanMessager;
	}

	public TestPlanModel createTestPlan(TestPlanRequestModel testPlan, int port) {
		TestPlanModel testPlanModel = new TestPlanModel();
		testPlanModel.setName(testPlan.getTestPlanName());
		if (testPlan.getScriptList() != null
				&& testPlan.getScriptList().size() > 0) {
			List<RunningScriptModel> scriptList = createRunningScriptModel(testPlan
					.getScriptList());
			testPlanModel.setRunningScriptModels(scriptList);
		}
		if (testPlan.getIpList() != null && testPlan.getIpList().size() > 0) {
			List<MonitorModel> ipList = createMonitorModel(
					testPlan.getIpList(), port);
			testPlanModel.setMonitorModels(ipList);
		} else
			testPlanModel.setMonitorModels(new ArrayList<MonitorModel>());

		return testPlanModel;
	}

	private List<RunningScriptModel> createRunningScriptModel(
			List<WebScriptModel> scriptParam) {

		List<RunningScriptModel> scriptList = new ArrayList<RunningScriptModel>();

		for (WebScriptModel scriptModel : scriptParam) {
			RunningScriptModel runnningScriptModel = new RunningScriptModel();
			runnningScriptModel.setScriptId(scriptModel.getId());
			runnningScriptModel.setRequireLoad(scriptModel.getLoad());
			ScriptFilterOptionsModel scriptFilterOptionsModel = new ScriptFilterOptionsModel();
			scriptFilterOptionsModel.setFilterTypeMatches(scriptModel.getFilterTypeMatches());
			scriptFilterOptionsModel.setFilterTimer(scriptModel.isTimer());
			
			TestScriptConfig testScriptConfig = new TestScriptConfig();
			testScriptConfig.setCoolDown(scriptModel.getCooldown());
			testScriptConfig.setExecuteRange(scriptModel.getExecuteRange());
			testScriptConfig.setWarmUp(scriptModel.getWarmup());
			runnningScriptModel.setConfig(testScriptConfig);
			runnningScriptModel
			 .setScriptFilterOptionsModel(scriptFilterOptionsModel);
			scriptList.add(runnningScriptModel);
		}
		return scriptList;
	}

	private List<MonitorModel> createMonitorModel(List<String> ipParam, int port) {
		List<MonitorModel> ipList = new ArrayList<MonitorModel>();
		for (String ip : ipParam) {
			MonitorModel monitorModel = new MonitorModel();
			monitorModel.setHostName(ip);
			monitorModel.setPort(port);
			ipList.add(monitorModel);
		}
		return ipList;
	}

	public List<ResultModel> extractResultModelList(
			TestPlanScriptBriefResultModel testPlanScriptBriefResultModel,
			String fieldName) {
		if (testPlanScriptBriefResultModel.getScriptBriefResultModels() == null) {
			return new LinkedList<ResultModel>();
		}
		List<ResultModel> resultModels = new ArrayList<ResultModel>();
		for (ScriptBriefResultModel scriptBriefResultModel : testPlanScriptBriefResultModel
				.getScriptBriefResultModels()) {

			List<String> fieldNames = new ArrayList<String>();
			fieldNames.add(fieldName);
			ResultModel resultModel;
			try {
				resultModel = ChangeToResultModel.getResultModel(
						scriptBriefResultModel, fieldNames);

				resultModel.setFinished(scriptBriefResultModel.isFinished());
				resultModel.setTime(scriptBriefResultModel.getSamplingTime());
				resultModels.add(resultModel);
			} catch (NoSuchFieldException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		System.out.println("resultLength:" + resultModels.size());
		return resultModels;

	}

	public List<BehaviorStatusCodeResultModel> getAllBehaviorStatusCodeResultModels(
			String accessToken, String testPlanId) {
		TestPlanResultModel testPlanResultModel = this.getTestPlanMessager()
				.getRunningTestInfo(accessToken, testPlanId);
		if (testPlanResultModel == null) {
			Logger.getLogger(this.getClass()).info(
					"testPlan is null:" + testPlanId);
			return null;
		}
		List<ScriptHandleModel> scriptList = testPlanResultModel.getScripts();
		if (scriptList == null) {
			return null;
		}
		List<BehaviorStatusCodeResultModel> behaviorStatusCodeResultModels = new LinkedList<BehaviorStatusCodeResultModel>();
		for (ScriptHandleModel scriptHandleModel : scriptList) {
			ScriptBehaviorsBriefModel scriptBehaviorBriefModel = this
					.getTestPlanMessager().getScriptBehaviorsBriefResult(
							accessToken, testPlanId,
							scriptHandleModel.getScriptId().toString());
			behaviorStatusCodeResultModels
					.addAll(extractBehaviorStatusCodeResultModels(scriptBehaviorBriefModel));
		}
		return behaviorStatusCodeResultModels;

	}

	private List<BehaviorStatusCodeResultModel> extractBehaviorStatusCodeResultModels(
			ScriptBehaviorsBriefModel scriptBehaviorsBriefModel) {
		List<BehaviorStatusCodeResultModel> behaviorStatusCodeResultModels = new ArrayList<BehaviorStatusCodeResultModel>();
		if (scriptBehaviorsBriefModel == null
				|| scriptBehaviorsBriefModel.getBehaviorBriefModels() == null) {
			return behaviorStatusCodeResultModels;
		}
		for (BehaviorBriefModel behaviorBriefModel : scriptBehaviorsBriefModel
				.getBehaviorBriefModels()) {

			if (behaviorBriefModel.getDetailStatusCodeResultModels() != null)
				behaviorStatusCodeResultModels.addAll(behaviorBriefModel
						.getDetailStatusCodeResultModels());
		}
		return behaviorStatusCodeResultModels;
	}

	public long getTotalCount(Map<String, Long> urlContentTypeCountMap) {

		Set<String> keys = urlContentTypeCountMap.keySet();
		Iterator<String> iterator = keys.iterator();
		long totalCount = 0;
		while (iterator.hasNext()) {
			totalCount += urlContentTypeCountMap.get(iterator.next());
		}
		return totalCount;
	}

	public Map<String, Double> getUrlContentTypePercent(
			Map<String, Long> urlContentTypeCountMap) {
		long totalCount = this.getTotalCount(urlContentTypeCountMap);
		if (urlContentTypeCountMap == null)
			return null;

		if (totalCount == 0)
			return null;
		Map<String, Double> urlContentTypePercentMap = new HashMap<String, Double>();
		Set<String> keys = urlContentTypeCountMap.keySet();
		Iterator<String> iterator = keys.iterator();
		while (iterator.hasNext()) {
			String key = iterator.next();
			double percent = (double) urlContentTypeCountMap.get(key)
					/ (double) totalCount * 100;
			urlContentTypePercentMap.put(key, new Double(percent));
		}
		return urlContentTypePercentMap;

	}
}
