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

import java.io.ByteArrayInputStream;
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.internal.registry.ExtensionRegistry;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.spi.RegistryContributor;
import org.eclipse.equinox.internal.p2.artifact.repository.MirrorEvent;
import org.eclipse.equinox.internal.p2.engine.*;
import org.eclipse.equinox.internal.p2.metadata.TouchpointData;
import org.eclipse.equinox.internal.p2.metadata.TouchpointInstruction;
import org.eclipse.equinox.internal.p2.touchpoint.eclipse.Util;
import org.eclipse.equinox.internal.p2.touchpoint.eclipse.actions.ActionConstants;
import org.eclipse.equinox.internal.p2.touchpoint.eclipse.actions.RemoveRepositoryAction;
import org.eclipse.equinox.internal.provisional.p2.core.eventbus.ProvisioningListener;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.engine.*;
import org.eclipse.equinox.p2.engine.spi.ProvisioningAction;
import org.eclipse.equinox.p2.metadata.*;
import org.eclipse.equinox.p2.query.IQueryResult;
import org.eclipse.equinox.p2.query.QueryUtil;
import org.eclipse.equinox.p2.repository.IRepository;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRequest;
import org.eclipse.equinox.p2.tests.AbstractProvisioningTest;
import org.eclipse.equinox.p2.tests.TestActivator;
import org.junit.*;

public class ProvisioningEventTest extends AbstractProvisioningTest {
	private IEngine engine;
	private File testProvisioning;

	@Override
	@Before
	public void setUp() throws Exception {
		engine = getEngine();
		testProvisioning = new File(System.getProperty("java.io.tmpdir"), "testProvisioning");
		delete(testProvisioning);
		testProvisioning.mkdir();
	}

	@Override
	@After
	public void tearDown() throws Exception {
		engine = null;
		delete(testProvisioning);
	}

	@Test
	public void testCollectEvent() throws ProvisionException, OperationCanceledException, InterruptedException {
		class ProvTestListener implements ProvisioningListener {
			int requestsNumber = 0;
			boolean called = false;
			boolean mirrorEevent = false;
			CountDownLatch latch = new CountDownLatch(1);

			@Override
			public void notify(EventObject o) {
				if (o instanceof CollectEvent) {
					if (((CollectEvent) o).getType() == CollectEvent.TYPE_OVERALL_START && ((CollectEvent) o).getRepository() == null) {
						called = true;
						IArtifactRequest[] requests = ((CollectEvent) o).getDownloadRequests();
						requestsNumber = requests.length;
					}
				} else if (o instanceof MirrorEvent) {
					mirrorEevent = true;
					System.out.println(((MirrorEvent) o).getDownloadStatus());
				} else if (o instanceof CommitOperationEvent || o instanceof RollbackOperationEvent)
					latch.countDown();
			}
		}
		final ProvTestListener listener = new ProvTestListener();
		getEventBus().addListener(listener);
		try {
			URI repoLoc = getTestData("Load test data.", "/testData/testRepos/updateSite").toURI();
			IProfile profile = createProfile("test");
			// clean possible cached artifacts
			IArtifactRepository bundlePool = Util.getBundlePoolRepository(getAgent(), profile);
			bundlePool.removeAll(new NullProgressMonitor());
			ProvisioningContext context = new ProvisioningContext(getAgent());
			context.setArtifactRepositories(new URI[] {repoLoc});
			context.setMetadataRepositories(new URI[] {repoLoc});
			IProvisioningPlan plan = engine.createPlan(profile, context);
			IQueryResult<IInstallableUnit> allIUs = getMetadataRepositoryManager().loadRepository(repoLoc, null).query(QueryUtil.ALL_UNITS, null);
			for (IInstallableUnit iu : allIUs.toSet()) {
				plan.addInstallableUnit(iu);
			}
			IStatus status = engine.perform(plan, new NullProgressMonitor());
			assertTrue("Provisioning was failed.", status.isOK());
			//			// make sure the listener handles all event already that are dispatched asynchronously
			listener.latch.await(10, TimeUnit.SECONDS);
			assertTrue("Collect event wasn't dispatched.", listener.called);
			assertEquals("Collect event didn't report expected artifacts to be downloaded.", 19, listener.requestsNumber);
			assertTrue("Mirror event wasn't dispatched.", listener.mirrorEevent);
		} finally {
			getEventBus().removeListener(listener);
		}
	}

	@Test
	public void testPhaseEvent() throws ProvisionException, OperationCanceledException, InterruptedException {
		final String[] phaseSets = new String[] {PhaseSetFactory.PHASE_COLLECT, PhaseSetFactory.PHASE_CHECK_TRUST, PhaseSetFactory.PHASE_INSTALL, PhaseSetFactory.PHASE_CONFIGURE};

		class ProvTestListener implements ProvisioningListener {
			String publishUnWantedPhaseEvent = null;
			int publishUnWantedPhaseType = 0;
			List<String> phaseStartEventToBePublised = new ArrayList<>(Arrays.asList(phaseSets));
			List<String> phaseEndEventToBePublised = new ArrayList<>(Arrays.asList(phaseSets));
			CountDownLatch latch = new CountDownLatch(1);

			@Override
			public void notify(EventObject o) {
				if (o instanceof PhaseEvent) {
					PhaseEvent event = (PhaseEvent) o;
					if (event.getType() == PhaseEvent.TYPE_START) {
						if (!phaseStartEventToBePublised.remove(event.getPhaseId()))
							publishUnWantedPhaseEvent = event.getPhaseId();
					} else if (event.getType() == PhaseEvent.TYPE_END) {
						if (!phaseEndEventToBePublised.remove(event.getPhaseId()))
							publishUnWantedPhaseEvent = event.getPhaseId();
					} else
						publishUnWantedPhaseType = event.getType();
				} else if (o instanceof CommitOperationEvent || o instanceof RollbackOperationEvent)
					latch.countDown();
			}
		}
		final ProvTestListener listener = new ProvTestListener();
		getEventBus().addListener(listener);
		try {
			URI repoLoc = getTestData("Load test data.", "/testData/testRepos/updateSite").toURI();
			IProfile profile = createProfile("test");
			ProvisioningContext context = new ProvisioningContext(getAgent());
			context.setArtifactRepositories(new URI[] {repoLoc});
			context.setMetadataRepositories(new URI[] {repoLoc});
			IProvisioningPlan plan = engine.createPlan(profile, context);
			IQueryResult<IInstallableUnit> allIUs = getMetadataRepositoryManager().loadRepository(repoLoc, null).query(QueryUtil.ALL_UNITS, null);
			for (IInstallableUnit iu : allIUs.toSet()) {
				plan.addInstallableUnit(iu);
			}
			IStatus status = engine.perform(plan, PhaseSetFactory.createPhaseSetIncluding(phaseSets), new NullProgressMonitor());
			assertTrue("Provisioning was failed.", status.isOK());
			// make sure the listener handles all event already that are dispatched asynchronously
			listener.latch.await(10, TimeUnit.SECONDS);
			assertNull("Published phase event with unwanted phase id.", listener.publishUnWantedPhaseEvent);
			assertEquals("Published unwanted type of phase event.", 0, listener.publishUnWantedPhaseType);
			assertEquals("Expected Phase start event is not published.", new ArrayList<String>(0), listener.phaseStartEventToBePublised);
			assertEquals("Expected Phase end event is not published.", new ArrayList<String>(0), listener.phaseEndEventToBePublised);
		} finally {
			getEventBus().removeListener(listener);
		}
	}

	@Test
	public void testConfigureUnConfigureEvent() throws InterruptedException {
		final String iuId = "test";
		class ProvTestListener implements ProvisioningListener {
			int preConfigureEvent = 0;
			int postConfigureEvent = 0;
			int preUnConfigureEvent = 0;
			int postUnConfigureEvent = 0;
			CountDownLatch latch = new CountDownLatch(2);

			@Override
			public void notify(EventObject o) {
				if (o instanceof InstallableUnitEvent) {
					InstallableUnitEvent event = (InstallableUnitEvent) o;
					if (event.getPhase().equals(PhaseSetFactory.PHASE_CONFIGURE) && event.isConfigure() && event.getInstallableUnit().getId().equals(iuId)) {
						if (event.isPre())
							preConfigureEvent++;
						else if (event.isPost())
							postConfigureEvent++;
					} else if (event.getPhase().equals(PhaseSetFactory.PHASE_UNCONFIGURE) && event.isUnConfigure() && event.getInstallableUnit().getId().equals(iuId)) {
						if (event.isPre())
							preUnConfigureEvent++;
						else if (event.isPost())
							postUnConfigureEvent++;
					}
				} else if (o instanceof CommitOperationEvent || o instanceof RollbackOperationEvent)
					latch.countDown();
			}
		}
		final ProvTestListener listener = new ProvTestListener();
		getEventBus().addListener(listener);

		try {
			IProfile profile = createProfile("testConfigureEvent");
			IProvisioningPlan plan = engine.createPlan(profile, null);

			final String testLocation = "http://download.eclipse.org/releases/juno";
			// remove the existing location in case it has
			Map<String, Object> args = new HashMap<>();
			args.put(ActionConstants.PARM_AGENT, getAgent());
			args.put("location", testLocation);
			args.put("type", Integer.toString(IRepository.TYPE_ARTIFACT));
			args.put("enabled", "true");
			new RemoveRepositoryAction().execute(args);

			Map<String, ITouchpointInstruction> data = new HashMap<>();
			Map<String, String> parameters = new HashMap<>();
			parameters.put("location", testLocation);
			parameters.put("type", Integer.toString(IRepository.TYPE_ARTIFACT));
			parameters.put("name", "Juno");
			parameters.put("enabled", "true");
			data.put(PhaseSetFactory.PHASE_CONFIGURE, new TouchpointInstruction(TouchpointInstruction.encodeAction("addRepository", parameters), null));
			IInstallableUnit testIU = createResolvedIU(createEclipseIU(iuId, Version.create("1.0.0"), new IRequirement[0], new TouchpointData(data)));
			plan.addInstallableUnit(testIU);
			IStatus result = engine.perform(plan, PhaseSetFactory.createDefaultPhaseSet(), new NullProgressMonitor());
			assertTrue("0.2", result.isOK());
			Set<IInstallableUnit> installedIUs = profile.available(QueryUtil.ALL_UNITS, null).toUnmodifiableSet();
			assertEquals("0.3", 1, installedIUs.size());
			plan = engine.createPlan(profile, null);
			plan.removeInstallableUnit(testIU);
			result = engine.perform(plan, PhaseSetFactory.createDefaultPhaseSet(), new NullProgressMonitor());
			assertTrue("0.4", result.isOK());
			// make sure the listener handles all event already that are dispatched asynchronously
			listener.latch.await(10, TimeUnit.SECONDS);
			assertEquals("0.5", 1, listener.preConfigureEvent);
			assertEquals("0.6", 1, listener.postConfigureEvent);
			assertEquals("0.7", 1, listener.preUnConfigureEvent);
			assertEquals("0.8", 1, listener.postUnConfigureEvent);
		} finally {
			getEventBus().removeListener(listener);
		}
	}

	public static class AlwaysFail extends ProvisioningAction {

		@Override
		public IStatus execute(Map<String, Object> parameters) {
			int a = 1;
			if (a == 1)
				throw new NullPointerException("no reason");
			return null;
		}

		@Override
		public IStatus undo(Map<String, Object> parameters) {
			return null;
		}

	}

	@Test
	public void testConfigureUndoEvent() throws InterruptedException {
		final String iuId = "test";
		final String failureIU = "alwaysFail";
		class ProvTestListener implements ProvisioningListener {
			int preConfigureEvent = 0;
			int postConfigureEvent = 0;
			int preUnConfigureEventForUndo = 0;
			int postUnConfigureEventForUndo = 0;
			CountDownLatch latch = new CountDownLatch(1);

			@Override
			public void notify(EventObject o) {
				if (o instanceof InstallableUnitEvent) {
					InstallableUnitEvent event = (InstallableUnitEvent) o;
					if (event.getPhase().equals(PhaseSetFactory.PHASE_CONFIGURE) && event.getInstallableUnit().getId().equals(iuId)) {
						if (event.isConfigure() && event.isPre())
							preConfigureEvent++;
						else if (event.isConfigure() && event.isPost())
							postConfigureEvent++;
						else if (event.isUnConfigure() && event.isPre())
							preUnConfigureEventForUndo++;
						else if (event.isUnConfigure() && event.isPost())
							postUnConfigureEventForUndo++;
					} else if (event.getPhase().equals(PhaseSetFactory.PHASE_CONFIGURE) && event.getInstallableUnit().getId().equals(failureIU)) {
						if (event.isConfigure() && event.isPre()) {
							preConfigureEvent++;
						} else if (event.isConfigure() && event.isPost())
							postConfigureEvent++;
						else if (event.isUnConfigure() && event.isPre())
							preUnConfigureEventForUndo++;
						else if (event.isUnConfigure() && event.isPost())
							postUnConfigureEventForUndo++;
					}
				} else if (o instanceof CommitOperationEvent || o instanceof RollbackOperationEvent)
					latch.countDown();
			}
		}
		final ProvTestListener listener = new ProvTestListener();
		getEventBus().addListener(listener);

		try {
			final String customTouchPoint = "<extension point=\"org.eclipse.equinox.p2.engine.actions\"> <action class=\"org.eclipse.equinox.p2.tests.engine.ProvisioningEventTest.AlwaysFail\" name=\"alwaysFail\" touchpointType=\"org.eclipse.equinox.p2.osgi\" touchpointVersion=\"1.0.0\" version=\"1.0.0\"></action></extension>";
			ByteArrayInputStream input = new ByteArrayInputStream(customTouchPoint.getBytes());
			IExtensionRegistry registry = Platform.getExtensionRegistry();
			registry.addContribution(input, new RegistryContributor(TestActivator.PI_PROV_TESTS, "p2 tests", null, null), false, "Always Fail TouchPoint Action", null, ((ExtensionRegistry) registry).getTemporaryUserToken());

			IProfile profile = createProfile("testConfigureEvent");
			IProvisioningPlan plan = engine.createPlan(profile, null);
			Map<String, ITouchpointInstruction> data = new HashMap<>();
			data.put(PhaseSetFactory.PHASE_CONFIGURE, MetadataFactory.createTouchpointInstruction("instructionparsertest.goodAction()", null));
			IInstallableUnit testIU = createResolvedIU(createIU(iuId, Version.create("1.0.0"), null, new IRequirement[0], BUNDLE_CAPABILITY, NO_PROPERTIES, ITouchpointType.NONE, new TouchpointData(data), false));
			plan.addInstallableUnit(testIU);
			data = new HashMap<>(1);
			data.put(PhaseSetFactory.PHASE_CONFIGURE, new TouchpointInstruction("alwaysFail();", null));
			plan.addInstallableUnit(createResolvedIU(createEclipseIU(failureIU, Version.create("1.0.0"), new IRequirement[0], new TouchpointData(data))));
			IStatus result = engine.perform(plan, PhaseSetFactory.createDefaultPhaseSet(), new NullProgressMonitor());
			assertFalse(result.isOK());
			// make sure the listener handles all event already that are dispatched asynchronously
			listener.latch.await(10, TimeUnit.SECONDS);
			assertEquals("0.5", 2, listener.preConfigureEvent);
			assertEquals("0.6", 1, listener.postConfigureEvent);
			assertEquals("0.7", 1, listener.preUnConfigureEventForUndo);
			assertEquals("0.8", 2, listener.postUnConfigureEventForUndo);
		} finally {
			getEventBus().removeListener(listener);
		}
	}
}