package org.bench4q.master.unitTest.entity;

import static org.junit.Assert.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.xml.bind.JAXBException;

import org.apache.log4j.Logger;
import org.bench4q.master.domain.entity.Agent;
import org.bench4q.master.domain.entity.Monitor;
import org.bench4q.master.domain.entity.TestPlan;
import org.bench4q.master.domain.entity.TestPlanScript;
import org.bench4q.master.domain.factory.TestPlanFactory;
import org.bench4q.master.domain.service.TestPlanService;
import org.bench4q.master.exception.ExceptionLog;
import org.bench4q.master.unitTest.TestBase_MakeUpTestPlan;
import org.bench4q.share.enums.master.TestPlanStatus;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:mockHttpMesseger-context.xml" })
public class Test_TestPlan extends TestBase_MakeUpTestPlan {
	private List<Agent> testcase2 = new ArrayList<Agent>();
	{
		Random random = new Random(212);
		testcase2.add(Agent.createAgentWithoutId(
				random.nextInt(256) + ".0.0.2", 6565, 500));
	}
	private TestPlanService testPlanService;
	private TestPlanFactory testPlanFactory;

	public TestPlanService getTestPlanService() {
		return testPlanService;
	}

	@Autowired
	public void setTestPlanService(TestPlanService testPlanService) {
		this.testPlanService = testPlanService;
	}

	public TestPlanFactory getTestPlanFactory() {
		return testPlanFactory;
	}

	@Autowired
	public void setTestPlanFactory(TestPlanFactory testPlanFactory) {
		this.testPlanFactory = testPlanFactory;
	}

	@Before
	public void prepare() {
		for (Agent agent : this.testcase2) {
			this.getAgentService().addAgentToPool(agent);
		}
		this.getHaPool().checkAllHeartBeat();
		submitATestPlanWithOneScript();
	}

	@After
	public void cleanUp() throws InterruptedException {
		cleanUpForTestPlanRunning();
		for (Agent agent : this.testcase2) {
			this.getAgentRepository().detach(agent.getHostName());
		}
	}

	@Test
	public void testDoAfterRun() throws InterruptedException, JAXBException {
		assertNotNull(getTestPlanRunIdUuid());
		try {
			TestPlan testPlanInDomain = this.getTestPlanFactory()
					.convertToDomain(
							this.getTestPlanRepository().getTestPlanInDomainBy(
									getTestPlanRunIdUuid()));
			testPlanInDomain.run();
			assertEquals(TestPlanStatus.InRunning.name(),
					testPlanInDomain.getCurrentStatus());
			Thread.sleep(4000);
			for (Monitor monitor : getTestPlan().getMonitors()) {
				assertTrue(monitor.getResults().size() > 0);
			}

			for (TestPlanScript testPlanScript : getTestPlan()
					.getTestPlanScripts()) {
				Logger.getLogger(Test_TestPlan.class).info(
						"testPlanScript:"
								+ testPlanScript.getTestPlanScriptResults()
										.size());
				assertTrue(testPlanScript.getTestPlanScriptResults().size() > 1);
			}
		} catch (Exception e) {
			Logger.getLogger(Test_TestPlan.class).info(
					ExceptionLog.getStackTrace(e));
		}
	}

	private TestPlan getTestPlan() {
		TestPlan testPlanFromRepo = this.getTestPlanRepository()
				.getTestPlanInDomainBy(getTestPlanRunIdUuid());
		TestPlan testPlanInDomain = this.getTestPlanFactory().convertToDomain(
				testPlanFromRepo);
		return testPlanInDomain;
	}

	@Test
	public void test_Run() {
		int startLoad = this.getHaPool().getCurrentAvailableLoad();
		TestPlan testPlanInDomain = this.getTestPlanFactory().convertToDomain(
				this.getTestPlanRepository().getTestPlanInDomainBy(
						getTestPlanRunIdUuid()));
		testPlanInDomain.run();
		assertEquals(TestPlanStatus.InRunning.name(),
				testPlanInDomain.getCurrentStatus());
		assertEquals(TestPlanStatus.InRunning.name(),
				testPlanInDomain.getCurrentStatus());
		TestPlanScript script = testPlanInDomain
				.extracSpecifiedScript(getUserFirstScript(this
						.getUserRepository().getUser("admin")));
		script.stop();
		assertTrue(script.isFinish());
		this.getHaPool().checkAllHeartBeat();
		assertEquals(startLoad, this.getHaPool().getCurrentAvailableLoad());
	}

	@Test
	public void test_stop() {
		TestPlan testPlan = this.getTestPlanRepository().getTestPlanInDomainBy(
				this.getTestPlanRunIdUuid());
		testPlan.run();
		assertFalse(testPlan.isFinish());
		assertEquals(TestPlanStatus.InRunning.toString(),
				testPlan.getCurrentStatus());
		testPlan.stop();
		assertEquals(TestPlanStatus.Complete.toString(),
				testPlan.getCurrentStatus());
		assertTrue(testPlan.isFinish());
	}
}
