package org.bench4q.master.domain.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import org.apache.log4j.Logger;
import org.bench4q.master.domain.entity.TestPlanScript;
import org.bench4q.master.domain.entity.TestPlanScriptResult;
import org.bench4q.master.domain.repository.TestPlanRepository;
import org.bench4q.master.exception.ExceptionLog;
import org.bench4q.master.helper.SessionHelper;
import org.bench4q.share.helper.MarshalHelper;
import org.bench4q.share.models.master.statistics.ScriptBehaviorsBriefModel;
import org.bench4q.share.models.master.statistics.ScriptBriefResultModel;
import org.bench4q.share.models.master.statistics.ScriptPagesBriefModel;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class TestPlanScriptResultService {
	private TestPlanRepository testPlanRepository;
	private SessionHelper sessionHelper;
	private static Logger logger = Logger
			.getLogger(TestPlanScriptResultService.class);

	private SessionHelper getSessionHelper() {
		return sessionHelper;
	}

	@Autowired
	private void setSessionHelper(SessionHelper sessionHelper) {
		this.sessionHelper = sessionHelper;
	}

	private TestPlanRepository getTestPlanRepository() {
		return testPlanRepository;
	}

	@Autowired
	private void setTestPlanRepository(TestPlanRepository testPlanRepository) {
		this.testPlanRepository = testPlanRepository;
	}

	public List<ScriptBriefResultModel> loadScriptBriefWithDuation(
			UUID testPlanId, int scriptId, long startTime) {
		Session session = this.getSessionHelper().openSession();
		List<ScriptBriefResultModel> result = new ArrayList<ScriptBriefResultModel>();
		try {
			List<TestPlanScriptResult> scriptResults = doGetTestPlanScriptResults(
					testPlanId, scriptId, startTime,
					ScriptBriefResultModel.class, session);
			System.out.println("Script Result Size from DB : "
					+ scriptResults.size());
			for (TestPlanScriptResult testPlanScriptResult : scriptResults) {
				result.add((ScriptBriefResultModel) MarshalHelper.unmarshal(
						ScriptBriefResultModel.class,
						testPlanScriptResult.getResultContent()));
			}
		} catch (Exception e) {
			logger.error(ExceptionLog.getStackTrace(e));
		} finally {
			if (session != null) {
				session.close();
			}
		}
		return result;
	}

	private List<TestPlanScriptResult> doGetTestPlanScriptResults(
			UUID testPlanId, int scriptId, long startTime, Class<?> resultType,
			Session session) {
		TestPlanScript testPlanScript = this.getTestPlanRepository()
				.getTestPlanInDomainBy(testPlanId)
				.extracSpecifiedScript(scriptId);
		@SuppressWarnings("unchecked")
		List<TestPlanScriptResult> results = (List<TestPlanScriptResult>) session
				.createCriteria(TestPlanScriptResult.class)
				.add(Restrictions.eq("testPlanScript", testPlanScript))
				.add(Restrictions.eq("resultType", resultType.getName()))
				.add(Restrictions.ge("createDatetime", new Date(startTime)))
				.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY).list();
		return results;
	}

	public ScriptBehaviorsBriefModel getLatestScriptBehaviorsBrief(
			UUID testPlanId, int scriptId) {
		Session session = this.getSessionHelper().openSession();
		try {
			TestPlanScriptResult testPlanScriptResult = doGetLastSampleResult(
					testPlanId, scriptId, ScriptBehaviorsBriefModel.class,
					session);
			if (testPlanScriptResult == null) {
				return new ScriptBehaviorsBriefModel();
			}
			return (ScriptBehaviorsBriefModel) MarshalHelper.unmarshal(
					ScriptBehaviorsBriefModel.class,
					testPlanScriptResult.getResultContent());
		} catch (Exception e) {
			logger.error(ExceptionLog.getStackTrace(e));
		} finally {
			if (session != null) {
				session.close();
			}
		}
		return new ScriptBehaviorsBriefModel();
	}

	private TestPlanScriptResult doGetLastSampleResult(UUID testPlanId,
			int scriptId, Class<?> resultType, Session session) {
		TestPlanScript testPlanScript = this.getTestPlanRepository()
				.getTestPlanInDomainBy(testPlanId)
				.extracSpecifiedScript(scriptId);
		@SuppressWarnings("unchecked")
		List<TestPlanScriptResult> results = (List<TestPlanScriptResult>) session
				.createCriteria(TestPlanScriptResult.class)
				.add(Restrictions.eq("testPlanScript", testPlanScript))
				.add(Restrictions.eq("resultType", resultType.getName()))
				.addOrder(Order.desc("createDatetime")).setFetchSize(1).list();
		if (results.size() > 0) {
			return results.get(0);
		}
		return null;
	}

	public ScriptPagesBriefModel getLatestScriptPagesBrief(UUID testPlanId,
			int scriptId) {
		Session session = this.getSessionHelper().openSession();
		ScriptPagesBriefModel result = new ScriptPagesBriefModel();
		try {
			TestPlanScriptResult testPlanScriptResult = doGetLastSampleResult(
					testPlanId, scriptId, ScriptPagesBriefModel.class, session);
			if (testPlanScriptResult == null) {
				return result;
			}
			result = (ScriptPagesBriefModel) MarshalHelper.unmarshal(
					ScriptPagesBriefModel.class,
					testPlanScriptResult.getResultContent());
		} catch (Exception e) {
			logger.error(ExceptionLog.getStackTrace(e));
		} finally {
			if (session != null) {
				session.close();
			}
		}
		return result;
	}

	public ScriptBriefResultModel getLatestScriptBriefResultModel(
			UUID testPlanId, int scriptId) {
		Session session = this.getSessionHelper().openSession();
		TestPlanScriptResult testPlanScriptResult = this.doGetLastSampleResult(
				testPlanId, scriptId, ScriptBriefResultModel.class, session);
		if (testPlanScriptResult == null) {
			return null;
		}
		return (ScriptBriefResultModel) MarshalHelper.tryUnmarshal(
				ScriptBriefResultModel.class,
				testPlanScriptResult.getResultContent());
	}

}
