/*******************************************************************************
 * Copyright (c) 2009, 2015 Xored Software Inc and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Xored Software Inc - initial API and implementation and/or initial documentation
 *******************************************************************************/
package org.eclipse.rcptt.internal.launching;

import static org.eclipse.rcptt.internal.core.RcpttPlugin.createStatus;

import java.io.ByteArrayInputStream;
import java.util.Collections;
import java.util.List;
import java.util.zip.ZipInputStream;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.rcptt.core.Q7;
import org.eclipse.rcptt.core.Q7Features;
import org.eclipse.rcptt.core.ecl.core.model.CreateReport;
import org.eclipse.rcptt.core.ecl.core.model.ExecutionPhase;
import org.eclipse.rcptt.core.ecl.core.model.GetReport;
import org.eclipse.rcptt.core.ecl.core.model.PrepareEnvironment;
import org.eclipse.rcptt.core.ecl.core.model.Q7CoreFactory;
import org.eclipse.rcptt.core.ecl.core.model.ResetVerifications;
import org.eclipse.rcptt.core.ecl.core.model.SetCommandsDelay;
import org.eclipse.rcptt.core.ecl.core.model.SetQ7Features;
import org.eclipse.rcptt.core.model.IQ7NamedElement;
import org.eclipse.rcptt.core.model.ModelException;
import org.eclipse.rcptt.ecl.core.ProcessStatus;
import org.eclipse.rcptt.ecl.core.Sequence;
import org.eclipse.rcptt.ecl.core.util.ECLBinaryResourceImpl;
import org.eclipse.rcptt.ecl.core.util.ScriptletFactory;
import org.eclipse.rcptt.ecl.internal.core.ProcessStatusConverter;
import org.eclipse.rcptt.internal.core.RcpttPlugin;
import org.eclipse.rcptt.internal.launching.ecl.EclScenarioExecutable;
import org.eclipse.rcptt.launching.AutLaunch;
import org.eclipse.rcptt.launching.IExecutable;
import org.eclipse.rcptt.launching.Q7LaunchUtils;
import org.eclipse.rcptt.launching.utils.TestSuiteUtils;
import org.eclipse.rcptt.parameters.ParametersFactory;
import org.eclipse.rcptt.parameters.ResetParams;
import org.eclipse.rcptt.reporting.Q7Info;
import org.eclipse.rcptt.reporting.core.ReportHelper;
import org.eclipse.rcptt.reporting.core.SimpleSeverity;
import org.eclipse.rcptt.sherlock.core.model.sherlock.report.LoggingCategory;
import org.eclipse.rcptt.sherlock.core.model.sherlock.report.Node;
import org.eclipse.rcptt.sherlock.core.model.sherlock.report.Report;
import org.eclipse.rcptt.sherlock.core.model.sherlock.report.ReportContainer;
import org.eclipse.rcptt.sherlock.core.streams.SherlockReportSession;
import org.eclipse.rcptt.tesla.core.TeslaFeatures;

import com.google.common.base.Objects;
import com.google.common.base.Preconditions;

public class PrepareExecutionWrapper extends Executable {

	@Override
	public void cancel(IStatus status) {
		// Handle cancellation caused by child failure.
		// Execution view may interrupt execution on first error.
		for (final Executable child : getChildren()) {
			IStatus childResult = handleChildResult(child.getResultStatus());
			if (child.getStatus() == State.COMPLETED && !childResult.isOK()) {
				return; // Execution will complete soon and this node will assume error result.
			}
		}
		super.cancel(status);
	}

	private final AutLaunch launch;
	private final Executable executable;
	private SherlockReportSession reportSession;

	private String resultReportID;

	public PrepareExecutionWrapper(AutLaunch launch, Executable executable) throws ModelException {
		super(executable.isDebug(), ExecutionPhase.AUTO, true);
		this.launch = launch;
		this.executable = executable;
		Preconditions.checkNotNull(getActualElement());
		Preconditions.checkNotNull(getActualElement().getID());
	}

	public Executable getExecutable() {
		return executable;
	}

	public AutLaunch getAut() {
		return launch;
	}

	@Override
	public void startLaunching() {
		executable.startLaunching();
	}

	@Override
	public Report getResultReport() {
		if (resultReportID != null && reportSession != null) {
			return reportSession.getReport(resultReportID);
		}
		return TestSuiteUtils.generateReport(getActualElement(), getResultStatus());
	}

	@Override
	public IStatus execute() throws InterruptedException {
		launch.resetState();
		PrepareEnvironment prepareEnvironment = Q7CoreFactory.eINSTANCE
				.createPrepareEnvironment();
		SetCommandsDelay commandsDelay = Q7CoreFactory.eINSTANCE.createSetCommandsDelay();
		commandsDelay.setDelay(Q7.INSTANCE.getCommandsExecutionDelay());
		TeslaFeatures.getInstance().getOption(TeslaFeatures.COMMAND_EXECUTION_DELAY)
				.setValue(Integer.toString(commandsDelay.getDelay()));
		SetQ7Features setQ7Features = Q7CoreFactory.eINSTANCE.createSetQ7Features();
		Q7LaunchUtils.setQ7Variable(setQ7Features, Q7LaunchUtils.Q7_CURRENT_TEST_VAR,
				getName());
		TeslaFeatures.getInstance().storeValues(setQ7Features.getFeatures());
		Q7Features.getInstance().storeValues(setQ7Features.getFeatures());
		Sequence command = ScriptletFactory.seq(prepareEnvironment, commandsDelay,
				setQ7Features);
		try {
			launch.execute(command);
			resetParams();
			resetVerifications();
		} catch (CoreException e) {
			return e.getStatus();
		} catch (Exception e) {
			return Q7LaunchingPlugin.createStatus(e);
		}
		try {
			createReport();
		} catch (CoreException e) {
			return e.getStatus();
		}
		if (executable instanceof GroupExecutable) {
			IExecutable rootExecutable = ((GroupExecutable) executable).getRoot();
			if (rootExecutable instanceof EclScenarioExecutable) {
				EclScenarioExecutable scenario = (EclScenarioExecutable) rootExecutable;
				TestEngineManager.getInstance().fireExecutionStarted(scenario);
			}
		}
		return executable.execute();
	}

	private Report getReport() throws InterruptedException, ModelException {
		Report resultReport = null;
		final String id = getActualElement().getID();
		Preconditions.checkNotNull(id);
		try {
			GetReport getReport = Q7CoreFactory.eINSTANCE.createGetReport();
			Object object = launch.execute(getReport);
			if (object instanceof Report) {
				resultReport = (Report) object;
			} else if (object instanceof ReportContainer) {
				ZipInputStream zin = new ZipInputStream(new ByteArrayInputStream(
						((ReportContainer) object).getContent()));
				try {
					// position the stream at the beginning of the entry data
					zin.getNextEntry();
					Resource res = new ECLBinaryResourceImpl();
					res.load(zin, null);
					EObject object2 = res.getContents().get(0);
					if (object2 instanceof Report) {
						resultReport = (Report) object2;
					} else {
						throw invalidObjectStatus(object2);
					}
				} catch (Exception e) {
					throw new CoreException(Q7LaunchingPlugin.createStatus(e.getMessage(), e));
				}
			} else if (object == null) {
				throw invalidObjectStatus(object);
			} else {
				throw invalidObjectStatus(object);
			}
			String reportId = ReportHelper.getInfo(resultReport.getRoot()).getId();
			if (!id.equals(reportId)) {
				throw new CoreException(createStatus("Expected item id: " + id + ", actual report id: " + reportId));
			}
		} catch (CoreException e) {
			resultReport = generateReport(e.getStatus());
		}
		Q7Info info = ReportHelper.getInfoOnly(resultReport.getRoot());
		if (info != null) {
			info.getVariant().clear();
			info.getVariant().addAll(getVariantName());
		}
		return resultReport;
	}

	private CoreException invalidObjectStatus(Object o) {
		String clazz = o == null ? "null" : o.getClass().getName();
		return new CoreException(createStatus("Expected: Report object, found: " + clazz));
	}

	private void resetParams() throws CoreException, InterruptedException {
		ResetParams cmd = ParametersFactory.eINSTANCE.createResetParams();
		launch.execute(cmd);
	}

	private void resetVerifications() throws CoreException, InterruptedException {
		ResetVerifications cmd = Q7CoreFactory.eINSTANCE.createResetVerifications();
		launch.execute(cmd);
	}

	private void createReport() throws CoreException, InterruptedException {
		CreateReport createReport = Q7CoreFactory.eINSTANCE.createCreateReport();
		createReport.setName(getName());
		createReport.setQ7info(getQ7Info(executable));
		launch.execute(createReport);
	}

	private static Q7Info getQ7Info(Executable executable) throws ModelException {
		IQ7NamedElement element = executable.getActualElement();
		return TestSuiteUtils.getQ7Info(element);
	}

	@Override
	public Executable[] getChildren() {
		return executable.getChildren();
	}

	public IQ7NamedElement getActualElement() {
		return executable.getActualElement();
	}

	public String getName() {
		return executable.getName();
	}

	public int getType() {
		return executable.getType();
	}

	private static void closeAllNodes(long endTime, Node node) {
		if (node.getEndTime() == 0) {
			node.setEndTime(endTime);
			node.setDuration(node.getEndTime() - node.getStartTime());
		}
		Q7Info info = ReportHelper.getInfo(node);
		for (Node child : node.getChildren()) {
			closeAllNodes(endTime, child);
			Q7Info childInfo = ReportHelper.getInfo(child);
			if (childInfo.getResult() == null) {
				ProcessStatus childStatus = RcpttPlugin.createProcessStatus(IStatus.ERROR, "" + child.getName()
						+ " result is not set");
				childInfo.setResult(childStatus);
				if (SimpleSeverity.create(info) == SimpleSeverity.OK)
					info.setResult(childStatus);
			}
		}
	}

	@Override
	public IStatus postExecute(IStatus status) {
		IStatus temp = executable.postExecute(status);
		if (status.isOK() && !temp.isOK())
			status = temp;
		Report resultReport = null;
		try {
			if (status.matches(IStatus.CANCEL)) {
				resultReport = generateReport(status);
			} else {
				// Take report from AUT
				resultReport = getReport();
				Node root = resultReport.getRoot();
				Q7Info rootInfo = ReportHelper.getInfo(root);
				assert rootInfo.getResult() == null;
				rootInfo.setResult(ProcessStatusConverter.toProcessStatus(status));
				closeAllNodes(root.getStartTime() + getTime(), root);
				if (status.isOK() && SimpleSeverity.create(rootInfo) != SimpleSeverity.OK) {
					status = ProcessStatusConverter.toIStatus(rootInfo.getResult());
				}

				for (IExecutable ch : getChildren()) {
					if (ch instanceof ScenarioExecutable) {
						rootInfo.setId(ch.getId());
						break;
					}
				}
				assert Objects.equal(rootInfo.getId(), getActualElement().getID());
			}
			return super.postExecute(status);
		} catch (InterruptedException e) {
			resultReport = generateReport(createStatus("Interrupted during report acquisition", e));
			return Status.CANCEL_STATUS;
		} catch (Throwable e) {
			RcpttPlugin.log(e);
			IStatus rv = RcpttPlugin.createStatus(e);
			resultReport = generateReport(rv);
			return rv;
		} finally {
			Preconditions.checkNotNull(resultReport);
			if (executable instanceof GroupExecutable) {
				IExecutable rootExecutable = ((GroupExecutable) executable).getRoot();
				if (rootExecutable instanceof EclScenarioExecutable) {
					EclScenarioExecutable scenario = (EclScenarioExecutable) rootExecutable;
					TestEngineManager.getInstance().fireExecutionCompleted(scenario, resultReport);
				}
			}
			if (this.reportSession != null) {
				resultReportID = this.reportSession.write(resultReport);
			}
			listeners.updateSessionCounters(this, status);
		}
	}

	private Report generateReport(IStatus status) {
		Report report = TestSuiteUtils.generateReport(getActualElement(), status);
		Node root = report.getRoot();
		root.setEndTime(root.getStartTime() + getTime());
		root.setDuration(root.getEndTime() - root.getStartTime());
		ReportHelper.appendLog(root, LoggingCategory.NORMAL, getLog());
		return report;
	}

	public void setReportSession(SherlockReportSession reportSession) {
		this.reportSession = reportSession;
	}

	public List<String> getVariantName() {
		Executable exx = getExecutable();
		if (exx instanceof GroupExecutable) {
			IExecutable ex = ((GroupExecutable) exx).getRoot();
			if (ex instanceof EclScenarioExecutable)
				return ((EclScenarioExecutable) ex).getVariantName();
		}
		return Collections.emptyList();
	}

	@Override
	public String toString() {
		return "Prepare: " + executable.toString();
	}

}
