package org.bench4q.agent.test;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;

import org.apache.commons.io.FileUtils;
import org.bench4q.agent.plugin.ParameterBarn;
import org.bench4q.agent.plugin.PluginManager;
import org.bench4q.agent.scenario.Scenario;
import org.bench4q.agent.scenario.engine.ScenarioContext;
import org.bench4q.agent.scenario.engine.Schedule;
import org.bench4q.agent.scenario.engine.VUser;
import org.bench4q.share.helper.TestHelper;
import org.bench4q.share.models.agent.ParameterModel;
import org.bench4q.share.models.agent.RunScenarioModel;
import org.bench4q.share.models.agent.scriptrecord.BatchModel;
import org.bench4q.share.models.agent.scriptrecord.BehaviorModel;
import org.bench4q.share.models.agent.scriptrecord.PageModel;
import org.bench4q.share.models.agent.scriptrecord.ScheduleModel;
import org.bench4q.share.models.agent.scriptrecord.UsePluginModel;
import org.bench4q.share.models.agent.scriptrecord.ScheduleModel.PointModel;
import org.springframework.beans.factory.annotation.Autowired;

public abstract class TestBase {
	private ParameterBarn basePara;
	private PluginManager pluginManager;

	private PluginManager getPluginManager() {
		return pluginManager;
	}

	@Autowired
	private void setPluginManager(PluginManager pluginManager) {
		this.pluginManager = pluginManager;
	}

	protected void createFileAndWriteContent(UUID testId, String paramName,
			String content) throws IOException {
		basePara = new ParameterBarn(testId.toString()) {
			@Override
			public String getValue(String var) {
				return null;
			}
		};
		File paramFile = new File(basePara.getFileFullPath(paramName));
		TestHelper.createFileIfNotExist(paramFile);
		FileUtils.writeStringToFile(paramFile, content);
	}

	protected void dropFiles(UUID testId) throws IOException {
		String fileFullPath = this.basePara.getFileFullPath("test");
		String dirPath = fileFullPath.substring(0,
				fileFullPath.lastIndexOf(System.getProperty("file.separator")));
		File dirFile = new File(dirPath);
		FileUtils.deleteDirectory(dirFile);
	}

	protected UsePluginModel buildCsvProviderWith(final String id,
			final String fileName, final String fieldNames) {
		UsePluginModel usePluginModel = new UsePluginModel() {
			{
				setId(id);
				setName("CsvProvider");
				setParameters(new ArrayList<ParameterModel>() {
					private static final long serialVersionUID = 1L;
					{
						add(ParameterModel
								.createParameter("fileName", fileName));
						add(ParameterModel.createParameter("separator", ","));
						add(ParameterModel.createParameter("fieldNames",
								fieldNames));
						add(ParameterModel.createParameter("shared",
								"Notenable"));
						add(ParameterModel.createParameter("loop", "enable"));
						add(ParameterModel.createParameter("loadAtRunTime",
								"Notenable"));
						add(ParameterModel.createParameter("commentPrefix",
								null));
					}
				});
			}
		};

		return usePluginModel;
	}

	public RunScenarioModel buildRunScenarioModelWith(
			List<UsePluginModel> plugins, BehaviorModel... behaviors) {
		RunScenarioModel runScenarioModel = new RunScenarioModel();
		UsePluginModel httpPlugin = new UsePluginModel() {
			{
				setId("http");
				setName("Http");
				setParameters(new ArrayList<ParameterModel>());
			}
		};
		for (UsePluginModel pluginModel : plugins) {
			runScenarioModel.getUsePlugins().add(pluginModel);
		}
		runScenarioModel.getUsePlugins().add(httpPlugin);
		int idGenerator = 1;
		PageModel page = new PageModel(idGenerator++);
		BatchModel batch = new BatchModel(idGenerator++);
		for (BehaviorModel behavior : behaviors) {
			batch.getBehaviors().add(behavior);
		}
		page.getBatches().add(batch);
		ScheduleModel scheduleModel = new ScheduleModel();
		List<PointModel> points = new LinkedList<ScheduleModel.PointModel>();
		points.add(new PointModel(0, 0));
		points.add(new PointModel(10000, 10));
		scheduleModel.setPoints(points);
		runScenarioModel.setScheduleModel(scheduleModel);
		runScenarioModel.getPages().add(page);
		return runScenarioModel;
	}

	public VUser createVUser(Scenario scenario, UUID testId) {
		return new VUser(buildScenarioContext(testId, scenario,
				10, pluginManager), 1, this.getPluginManager());
	}
	
	public static ScenarioContext buildScenarioContext(UUID testId,
			final Scenario scenario, int poolSize, PluginManager pluginManager) {
		ScenarioContext scenarioContext = ScenarioContext.buildScenarioContextWithoutScenario(
				testId, poolSize, pluginManager);
		return scenarioContext.addScenrio(scenario, Schedule.build(buildScheduleModel()), new Date().getTime());
	}
	
	public static ScheduleModel buildScheduleModel(){
		ScheduleModel scheduleModel = new ScheduleModel();
		List<PointModel> points = new LinkedList<ScheduleModel.PointModel>();
		points.add(new PointModel(0, 0));
		points.add(new PointModel(20 * 1000, 20));
		points.add(new PointModel(60 * 1000, 20));
		scheduleModel.setPoints(points);
		return scheduleModel;
	}
}
