/*******************************************************************************
 *  Copyright (c) 2007, 2017 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.equinox.p2.tests.engine;

import java.io.File;
import java.net.URI;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.equinox.internal.p2.director.ProfileChangeRequest;
import org.eclipse.equinox.internal.p2.engine.*;
import org.eclipse.equinox.internal.p2.repository.DownloadProgressEvent;
import org.eclipse.equinox.internal.p2.touchpoint.natives.Util;
import org.eclipse.equinox.internal.provisional.p2.core.eventbus.ProvisioningListener;
import org.eclipse.equinox.internal.provisional.p2.repository.RepositoryEvent;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.engine.*;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.query.*;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository;
import org.eclipse.equinox.p2.tests.AbstractProvisioningTest;
import org.eclipse.equinox.p2.tests.TestActivator;
import org.junit.Test;

/**
 * Simple test of the engine API.
 */
public class PhaseSetTest extends AbstractProvisioningTest {
	PauseJob pause = null;

	public PhaseSetTest(String name) {
		super(name);
	}

	public PhaseSetTest() {
		super("");
	}

	public void testNullPhases() {
		try {
			new PhaseSet(null) {
				// empty PhaseSet
			};
		} catch (IllegalArgumentException exepcted) {
			return;
		}
		fail();
	}

	public void testNoTrustCheck() {
		IPhaseSet set1 = PhaseSetFactory.createDefaultPhaseSet();
		IPhaseSet set2 = PhaseSetFactory.createDefaultPhaseSetExcluding(new String[] {PhaseSetFactory.PHASE_CHECK_TRUST});
		assertTrue("1.0", !set1.equals(set2));
	}

	public void testEmptyPhases() {
		IProfile profile = createProfile("PhaseSetTest");
		PhaseSet phaseSet = new PhaseSet(new Phase[] {}) {
			// empty PhaseSet
		};
		InstallableUnitOperand op = new InstallableUnitOperand(createResolvedIU(createIU("iu")), null);
		InstallableUnitOperand[] operands = new InstallableUnitOperand[] {op};

		ProvisioningContext context = new ProvisioningContext(getAgent());
		IStatus result = phaseSet.perform(new EngineSession(null, profile, context), operands, new NullProgressMonitor());
		assertTrue(result.isOK());
	}

	@Test
	public void testPauseNotRunningPhaseSet() {
		PhaseSet set = (PhaseSet) PhaseSetFactory.createDefaultPhaseSet();
		assertFalse("Can pause not running phaseset.", set.pause());
	}

	@Test
	public void testResumeNotPausedPhaseSet() {
		PhaseSet set = (PhaseSet) PhaseSetFactory.createDefaultPhaseSet();
		assertFalse("Can resume not phaused phaseset.", set.resume());
	}

	abstract class PauseJob extends Job {
		public PauseJob(String name) {
			super(name);
		}

		private boolean isPaused = false;
		Job resume = null;

		public boolean isPaused() {
			return isPaused;
		}

		public void setPause(boolean paused) {
			isPaused = paused;
		}
	}

	@Test
	public void testPauseAndResume() throws ProvisionException, OperationCanceledException, InterruptedException {
		URI repoLoc = getTestData("Load test data.", "/testData/pausefeature").toURI();
		final PhaseSet phaseSet = (PhaseSet) PhaseSetFactory.createDefaultPhaseSet();
		pause = new PauseJob("pause") {
			@Override
			protected IStatus run(IProgressMonitor monitor) {
				if (!phaseSet.pause())
					return new Status(IStatus.ERROR, TestActivator.PI_PROV_TESTS, "pause() failed.");
				try {
					Thread.sleep(5000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				setPause(true);
				resume = new Job("resume") {
					@Override
					protected IStatus run(IProgressMonitor monitor1) {
						pause.setPause(false);
						if (!phaseSet.resume())
							return new Status(IStatus.ERROR, TestActivator.PI_PROV_TESTS, "resume() failed.");
						return Status.OK_STATUS;
					}
				};
				resume.schedule(10000);
				return Status.OK_STATUS;
			}
		};
		basicTest(repoLoc, phaseSet, pause, QueryUtil.createIUQuery("org.eclipse.equinox.launcher"), IStatus.OK, null);
		assertTrue("Pause job is failed.", pause.getResult().isOK());
		pause.resume.join();
		assertTrue("Resume job is failed.", pause.resume.getResult().isOK());
	}

	private void basicTest(URI repoURI, PhaseSet phaseSet, final PauseJob pauseJob, IQuery<IInstallableUnit> query, int expectedCode, IProgressMonitor monitor) throws ProvisionException, InterruptedException {
		class ProvTestListener implements ProvisioningListener {
			boolean hasProvisioningEventAfterPaused = false;
			CountDownLatch latch = new CountDownLatch(1);
			boolean canStart = false;

			@Override
			public void notify(EventObject o) {
				if (o instanceof BeginOperationEvent) {
					canStart = true;
				}
				if (o instanceof RepositoryEvent || o instanceof ProfileEvent)
					return;
				if (canStart && o instanceof DownloadProgressEvent) {
					// make sure to pause downloading after it has started
					pauseJob.schedule();
					canStart = false;
					return;
				}
				if (o instanceof CommitOperationEvent || o instanceof RollbackOperationEvent) {
					latch.countDown();
					pauseJob.cancel();
					return;
				}
				if (pauseJob.isPaused() && !(o instanceof PhaseEvent)) {
					hasProvisioningEventAfterPaused = true;
				}
			}
		}

		ProvTestListener listener = new ProvTestListener();
		getEventBus().addListener(listener);
		try {
			getMetadataRepositoryManager().loadRepository(repoURI, null);
			getArtifactRepositoryManager().loadRepository(repoURI, null);
			doProvisioning(repoURI, phaseSet, query, expectedCode, monitor);
			// make sure the listener handles all event already that are dispatched asynchronously
			listener.latch.await(10, TimeUnit.SECONDS);
			assertFalse("Engine still do provisioning after pausing.", listener.hasProvisioningEventAfterPaused);
			pauseJob.join();
		} finally {
			getEventBus().removeListener(listener);
		}
	}

	private void doProvisioning(URI repoLoc, final PhaseSet phaseSet, IQuery<IInstallableUnit> query, int expectedResult, IProgressMonitor monitor) throws ProvisionException {
		File testFolder = new File(System.getProperty("java.io.tmpdir"), "testProvisioning");
		delete(testFolder);
		testFolder.mkdir();
		final String profileId = "test";
		try {
			ProvisioningContext context = new ProvisioningContext(getAgent());
			context.setArtifactRepositories(new URI[] {repoLoc});
			context.setMetadataRepositories(new URI[] {repoLoc});
			IEngine engine = getEngine();
			// restrict the installation to 'linux & gtk & x86' to match the test repo
			Map<String, String> props = new HashMap<>();
			props.put(IProfile.PROP_ENVIRONMENTS, "osgi.ws=gtk,osgi.arch=x86,osgi.os=linux");
			props.put(IProfile.PROP_INSTALL_FOLDER, testFolder.getAbsolutePath());
			IProfile profile = createProfile(profileId, props);
			// clean cached artifacts
			IArtifactRepository artifactRepo = org.eclipse.equinox.internal.p2.touchpoint.eclipse.Util.getBundlePoolRepository(getAgent(), profile);
			artifactRepo.removeAll(new NullProgressMonitor());
			ProfileChangeRequest request = ProfileChangeRequest.createByProfileId(getAgent(), profile.getProfileId());
			IQueryResult<IInstallableUnit> toBeInstalledIUs = getMetadataRepositoryManager().loadRepository(repoLoc, null).query(query, null);
			assertFalse("Test case has problem to find IU to be installed.", toBeInstalledIUs.isEmpty());
			request.addAll(toBeInstalledIUs.toSet());
			IProvisioningPlan plan = getPlanner(getAgent()).getProvisioningPlan(request, context, null);
			assertTrue("Provisioning plan can't be resolved.", plan.getStatus().isOK());
			IStatus status = engine.perform(plan, phaseSet, monitor);
			assertEquals("The reture code of provisioning is not expected.", expectedResult, status.getSeverity());
		} finally {
			delete(testFolder);
			getProfileRegistry().removeProfile(profileId);
			Util.getDownloadCacheRepo(getAgent()).removeAll(new NullProgressMonitor());
		}
	}

	@Test
	public void testPauseAndResumeMoreThanOnce() throws ProvisionException, InterruptedException {
		//		URI repoLoc = URI.create("http://download.eclipse.org/releases/indigo");
		URI repoLoc = getTestData("Load test data.", "/testData/pausefeature").toURI();
		final PhaseSet phaseSet = (PhaseSet) PhaseSetFactory.createDefaultPhaseSet();
		final int threhold = 3;
		class ResumeJob extends Job {

			private PauseJob pauseJob;
			private int count = 0;

			public ResumeJob(String name, PauseJob pauseJob) {
				super(name);
				this.pauseJob = pauseJob;
			}

			@Override
			protected IStatus run(IProgressMonitor monitor) {
				pauseJob.setPause(false);
				if (!phaseSet.resume())
					return new Status(IStatus.INFO, TestActivator.PI_PROV_TESTS, "resume() failed.");
				if (count++ < threhold)
					pauseJob.schedule(10000);
				return Status.OK_STATUS;
			}
		}
		pause = new PauseJob("pause") {
			@Override
			protected IStatus run(IProgressMonitor monitor) {
				if (!phaseSet.pause())
					return new Status(IStatus.INFO, TestActivator.PI_PROV_TESTS, "pause() failed.");
				try {
					Thread.sleep(5000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				setPause(true);
				if (resume == null)
					resume = new ResumeJob("resume", this);
				resume.schedule(10000);
				return Status.OK_STATUS;
			}
		};

		basicTest(repoLoc, phaseSet, pause, QueryUtil.createLatestQuery(QueryUtil.createIUQuery("org.eclipse.equinox.executable.feature.group")), IStatus.OK, null);
	}

	@Test
	public void testCancelPausedProvisioing() throws ProvisionException, InterruptedException {
		URI repoLoc = getTestData("Load test data.", "/testData/pausefeature").toURI();
		final PhaseSet phaseSet = (PhaseSet) PhaseSetFactory.createDefaultPhaseSet();
		class ProvListener implements ProvisioningListener {
			boolean hasDownloadEvent = false;

			@Override
			public void notify(EventObject o) {
				if (o instanceof DownloadProgressEvent)
					hasDownloadEvent = true;
			}

		}
		final ProvListener listener = new ProvListener();
		getEventBus().addListener(listener);
		try {

			pause = new PauseJob("pause") {
				@Override
				protected IStatus run(IProgressMonitor monitor) {
					while (!listener.hasDownloadEvent) {
						try {
							Thread.sleep(10);
						} catch (InterruptedException e1) {
							e1.printStackTrace();
						}
					}
					if (!phaseSet.pause())
						return new Status(IStatus.ERROR, TestActivator.PI_PROV_TESTS, "pause() failed.");
					try {
						Thread.sleep(5000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					// wait seconds
					try {
						Thread.sleep(2000);
					} catch (InterruptedException e) {
						//
					}
					setPause(true);
					return Status.OK_STATUS;
				}
			};

			basicTest(repoLoc, phaseSet, pause, QueryUtil.createLatestQuery(QueryUtil.createIUQuery("org.eclipse.equinox.executable.feature.group")), IStatus.CANCEL, new NullProgressMonitor() {
				@Override
				public boolean isCanceled() {
					return pause.isPaused();
				}
			});
		} finally {
			getEventBus().removeListener(listener);
		}
	}
}
