/*******************************************************************************
 *  Copyright (c) 2007, 2018 IBM Corporation and others.
 *
 *  This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License 2.0
 *  which accompanies this distribution, and is available at
 *  https://www.eclipse.org/legal/epl-2.0/
 *
 *  SPDX-License-Identifier: EPL-2.0
 *
 *  Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.equinox.p2.tests.metadata;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.StringReader;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.xml.parsers.ParserConfigurationException;
import org.eclipse.equinox.internal.p2.core.helpers.OrderedProperties;
import org.eclipse.equinox.internal.p2.metadata.IRequiredCapability;
import org.eclipse.equinox.internal.p2.metadata.InstallableUnit;
import org.eclipse.equinox.internal.p2.metadata.InstallableUnitPatch;
import org.eclipse.equinox.internal.p2.metadata.RequiredCapability;
import org.eclipse.equinox.internal.p2.metadata.repository.io.MetadataParser;
import org.eclipse.equinox.internal.p2.metadata.repository.io.MetadataWriter;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.metadata.IInstallableUnitPatch;
import org.eclipse.equinox.p2.metadata.ILicense;
import org.eclipse.equinox.p2.metadata.IProvidedCapability;
import org.eclipse.equinox.p2.metadata.IRequirement;
import org.eclipse.equinox.p2.metadata.IRequirementChange;
import org.eclipse.equinox.p2.metadata.ITouchpointData;
import org.eclipse.equinox.p2.metadata.IUpdateDescriptor;
import org.eclipse.equinox.p2.metadata.MetadataFactory;
import org.eclipse.equinox.p2.metadata.MetadataFactory.InstallableUnitDescription;
import org.eclipse.equinox.p2.metadata.Version;
import org.eclipse.equinox.p2.metadata.VersionRange;
import org.eclipse.equinox.p2.metadata.expression.IMatchExpression;
import org.eclipse.equinox.p2.tests.AbstractProvisioningTest;
import org.eclipse.equinox.p2.tests.TestActivator;
import org.osgi.framework.BundleContext;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class IUPersistenceTest extends AbstractProvisioningTest {

	class IUStringParser extends MetadataParser {

		private final class IUDocHandler extends DocHandler {

			public IUDocHandler(String rootName, RootHandler rootHandler) {
				super(rootName, rootHandler);
			}

			@Override
			public void processingInstruction(String target, String data) throws SAXException {
				if (IU_TEST_TARGET.equals(target)) {
					Version iuTestVersion = extractPIVersion(target, data);
					if (!IU_TEST_VERSION.equals(iuTestVersion)) {
						throw new SAXException("Bad iu test version.");
					}
				}
			}
		}

		private final class TestHandler extends RootHandler {

			private InstallableUnit iu = null;

			private InstallableUnitHandler iuHandler = null;
			private List<InstallableUnitDescription> singleton = new ArrayList<>(1);

			public TestHandler() {
				super();
			}

			@Override
			protected void finished() {
				if (isValidXML()) {
					if (iuHandler != null && singleton.size() == 1) {
						iu = (InstallableUnit) iuHandler.getInstallableUnit();
					}
				}
			}

			public InstallableUnit getIU() {
				return iu;
			}

			@Override
			protected void handleRootAttributes(Attributes attributes) {
				parseAttributes(attributes, noAttributes, noAttributes);
			}

			@Override
			public void startElement(String name, Attributes attributes) {
				if (INSTALLABLE_UNIT_ELEMENT.equals(name)) {
					if (iuHandler == null) {
						iuHandler = new InstallableUnitHandler(this, attributes, singleton);
					} else {
						duplicateElement(this, name, attributes);
					}
				} else {
					invalidElement(name, attributes);
				}
			}
		}

		private IInstallableUnit theIU = null;

		public IUStringParser(BundleContext context, String bundleId) {
			super(context, bundleId);
		}

		@Override
		protected String getErrorMessage() {
			return "Error parsing installable unit string";
		}

		@Override
		protected Object getRootObject() {
			return theIU;
		}

		public void parse(String profileString) throws IOException {
			this.status = null;
			try {
				getParser();
				TestHandler testHandler = new TestHandler();
				xmlReader.setContentHandler(new IUDocHandler(IU_TEST_ELEMENT, testHandler));
				xmlReader.parse(new InputSource(new StringReader(profileString)));
				if (isValidXML()) {
					theIU = testHandler.getIU();
				}
			} catch (SAXException e) {
				throw new IOException(e.getMessage());
			} catch (ParserConfigurationException e) {
				fail();
			}
		}

	}

	class IUStringWriter extends MetadataWriter {

		public IUStringWriter(ByteArrayOutputStream stream) {
			super(stream, new ProcessingInstruction[] {ProcessingInstruction.makeTargetVersionInstruction(IU_TEST_TARGET, IU_TEST_VERSION)});
		}

		public void writeTest(IInstallableUnit iu) {
			start(IU_TEST_ELEMENT);
			writeInstallableUnit(iu);
			end(IU_TEST_ELEMENT);
			flush();
		}
	}

	private static IMatchExpression<IInstallableUnit> filter = InstallableUnit.parseFilter("(& (osgi.ws=win32) (osgi.os=win32) (osgi.arch=x86))"); // not really
	private static String id = "org.eclipse.osgi.services";

	private static String[][] instructions = new String[][] {new String[] {"manifest", "Manifest-Version: 1.0\\Bundle-Vendor: Eclipse.org\\Bundle-ContactAddress: www.eclipse.org\\...a whole bunch of other manifest content..."}, new String[] {"zipped", "true"}, //
			new String[] {"configure", "addProgramArg(programArg:-startup);addProgramArg(programArg:@artifact);"}}; //

	private final static String IU_TEST_ELEMENT = "test";

	private final static String IU_TEST_TARGET = "installableUnitTest";

	final static Version IU_TEST_VERSION = Version.create("0.0.1");

	// Randomly chose org.eclipse.osgi.services as the IU for testing persistence
	// but 'enhanced' it for better coverage.
	private static String PackagesNS = "osgi.packages";

	private static String[][] properties = new String[][] {new String[] {"equinox.p2.name", "OSGi Release 4.0.1 Services"}, //
			new String[] {"equinox.p2.description", "OSGi Service Platform Release 4.0.1 Service Interfaces and Classes"}, //
			new String[] {"equinox.p2.provider", "Eclipse.org"}, //
			new String[] {"equinox.p2.contact", "www.eclipse.org"}, //
			new String[] {"equinox.p2.copyright", "Copyright (c) 2003, 2004 IBM Corporation and others. A long-winded copyright notice."}};

	private static String[][] provides = new String[][] {new String[] {PackagesNS, "org.osgi.service.cm", "1.2.0"}, //
			new String[] {PackagesNS, "org.osgi.service.component", "1.0.0"}, //
			new String[] {PackagesNS, "org.osgi.service.device", "1.1.0"}, //
			new String[] {PackagesNS, "org.osgi.service.event", "1.1.0"}, //
			new String[] {PackagesNS, "org.osgi.service.http", "1.2.0"}, //
			new String[] {PackagesNS, "org.osgi.service.io", "1.0.0"}, //
			new String[] {PackagesNS, "org.osgi.service.log", "1.3.0"}, //
			new String[] {PackagesNS, "org.osgi.service.metatype", "1.1.0"}, //
			new String[] {PackagesNS, "org.osgi.service.provisioning", "1.1.0"}, //
			new String[] {PackagesNS, "org.osgi.service.upnp", "1.1.0"}, //
			new String[] {PackagesNS, "org.osgi.service.useradmin", "1.1.0"}, //
			new String[] {PackagesNS, "org.osgi.service.wireadmin", "1.0.0"}}; //

	private static String[][] requires = new String[][] {new String[] {PackagesNS, "javax.servlet", "0.0.0", "true"}, //
			new String[] {PackagesNS, "javax.servlet.http", "0.0.0", "true"}, //
			new String[] {PackagesNS, "org.osgi.framework", "1.2.0", "false"}}; //

	private static String[][] metaRequires = new String[][] {new String[] {PackagesNS, "some.actions1", "0.0.0", "true"}, //
			new String[] {PackagesNS, "some.actions2", "1.2.0", "false"}}; //

	private static Version version = Version.create("3.1.200.v20070605");

	private Map<String, String> propertyMap;

	private static String[][] addSelfCapability(IInstallableUnit iu, String[][] provideTuples) {
		String[][] augmentedProvides = new String[provideTuples.length + 1][3];
		IProvidedCapability self = getSelfCapability(iu);
		augmentedProvides[0] = new String[] {self.getNamespace(), self.getName(), self.getVersion().toString()};
		for (int i = 0; i < provideTuples.length; i++) {
			augmentedProvides[i + 1] = provideTuples[i];
		}
		return augmentedProvides;
	}

	private static Map<String, String> createProperties(String[][] keyValuePairs) {
		OrderedProperties props = new OrderedProperties(keyValuePairs.length);
		for (String[] nextPair : keyValuePairs) {
			props.put(nextPair[0], nextPair[1]);
		}
		return props;
	}

	private static IProvidedCapability[] createProvided(String[][] provideTuples) {
		IProvidedCapability[] provided = new IProvidedCapability[provideTuples.length];
		for (int i = 0; i < provideTuples.length; i++) {
			String[] nextTuple = provideTuples[i];
			provided[i] = MetadataFactory.createProvidedCapability(nextTuple[0], nextTuple[1], Version.create(nextTuple[2]));
		}
		// provided[provideTuples.length] = BUNDLE_CAPABILITY;
		return provided;
	}

	private static IRequirement[] createRequired(String[][] requireTuples) {
		IRequirement[] required = new IRequirement[requireTuples.length];
		for (int i = 0; i < requireTuples.length; i++) {
			String[] nextTuple = requireTuples[i];
			required[i] = MetadataFactory.createRequirement(nextTuple[0], nextTuple[1], new VersionRange(nextTuple[2]), null, Boolean.parseBoolean(nextTuple[3]), false);
		}
		return required;
	}

	private static ITouchpointData createTouchpointData(String[][] instructionData) {
		Map<String, Object> map = new LinkedHashMap<>(instructionData.length);
		for (String[] nextInstruction : instructionData) {
			map.put(nextInstruction[0], nextInstruction[1]);
		}
		return MetadataFactory.createTouchpointData(map);
	}

	private static IUpdateDescriptor createUpdateDescriptor() {
		return MetadataFactory.createUpdateDescriptor(id, new VersionRange(IU_TEST_VERSION, true, IU_TEST_VERSION, true), IUpdateDescriptor.HIGH, "desc");
	}

	private static String[][] extractProvides(IInstallableUnit iu) {
		Collection<IProvidedCapability> provydes = iu.getProvidedCapabilities();
		String[][] tuples = new String[provydes.size()][3];
		int i = 0;
		for (IProvidedCapability capability : provydes) {
			tuples[i++] = new String[] {capability.getNamespace(), capability.getName(), capability.getVersion().toString()};
		}
		return tuples;
	}

	private static String[][] extractRequires(IInstallableUnit iu) {
		Collection<IRequirement> requirements = iu.getRequirements();
		String[][] tuples = new String[requirements.size()][4];
		int i = 0;
		for (IRequirement requirement : requirements) {
			IRequiredCapability capability = (IRequiredCapability) requirement;
			tuples[i++] = new String[] {capability.getNamespace(), capability.getName(), capability.getRange().toString(), Boolean.valueOf(capability.getMin() == 0).toString()};
		}
		return tuples;
	}

	private static String[][] extractMetaRequires(IInstallableUnit iu) {
		Collection<IRequirement> requirements = iu.getMetaRequirements();
		String[][] tuples = new String[requirements.size()][4];
		int i = 0;
		for (IRequirement requirement : requirements) {
			IRequiredCapability capability = (IRequiredCapability) requirement;
			tuples[i++] = new String[] {capability.getNamespace(), capability.getName(), capability.getRange().toString(), Boolean.valueOf(capability.getMin() == 0).toString()};
		}
		return tuples;
	}

	private IInstallableUnitPatch createPatchIU() {
		propertyMap = createProperties(properties);
		propertyMap.put(MetadataFactory.InstallableUnitDescription.PROP_TYPE_PATCH, "true");
		IProvidedCapability[] additionalProvides = createProvided(provides);
		IRequirement[] requirements = createRequired(requires);
		IRequirement[] metaRequirements = createRequired(metaRequires);
		ITouchpointData tpData = createTouchpointData(instructions);
		IUpdateDescriptor update = createUpdateDescriptor();
		boolean singleton = false;
		IRequirementChange change1 = MetadataFactory.createRequirementChange(MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, "B", VersionRange.emptyRange, null, false, false, false), MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, "B", new VersionRange("[1.1.0, 1.3.0)"), null, false, false, true));
		IRequirementChange change2 = MetadataFactory.createRequirementChange(null, MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, "B", new VersionRange("[1.1.0, 1.3.0)"), null, false, false, true));
		IRequirementChange change3 = MetadataFactory.createRequirementChange(MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, "B", VersionRange.emptyRange, null, false, false, false), null);
		IRequirement[][] scope = new IRequirement[][] {{MetadataFactory.createRequirement("foo", "bar", null, null, true, true), MetadataFactory.createRequirement("foo", "bar", null, null, true, true)}, {MetadataFactory.createRequirement("zoo", "far", null, null, true, true)}};
		IInstallableUnitPatch iu = createIUPatch(id, version, filter, requirements, additionalProvides, propertyMap, TOUCHPOINT_OSGI, tpData, singleton, update, new IRequirementChange[] {change1, change2, change3}, scope, null, metaRequirements);
		return iu;
	}

	private IInstallableUnitPatch createPatchWithEmptyScope() {
		propertyMap = createProperties(properties);
		propertyMap.put(MetadataFactory.InstallableUnitDescription.PROP_TYPE_PATCH, "true");
		IProvidedCapability[] additionalProvides = createProvided(provides);
		IRequirement[] requirements = createRequired(requires);
		IRequirement[] metaRequirements = createRequired(metaRequires);
		ITouchpointData tpData = createTouchpointData(instructions);
		IUpdateDescriptor update = createUpdateDescriptor();
		boolean singleton = false;
		IRequirementChange change1 = MetadataFactory.createRequirementChange(MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, "B", VersionRange.emptyRange, null, false, false, false), MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, "B", new VersionRange("[1.1.0, 1.3.0)"), null, false, false, true));
		IRequirementChange change2 = MetadataFactory.createRequirementChange(null, MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, "B", new VersionRange("[1.1.0, 1.3.0)"), null, false, false, true));
		IRequirementChange change3 = MetadataFactory.createRequirementChange(MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, "B", VersionRange.emptyRange, null, false, false, false), null);
		IRequirement[][] scope = new IRequirement[][] {{}};
		IInstallableUnitPatch iu = createIUPatch(id, version, filter, requirements, additionalProvides, propertyMap, TOUCHPOINT_OSGI, tpData, singleton, update, new IRequirementChange[] {change1, change2, change3}, scope, null, metaRequirements);
		return iu;
	}

	public IInstallableUnit createPersistenceTestIU() {
		propertyMap = createProperties(properties);
		IProvidedCapability[] additionalProvides = createProvided(provides);
		IRequirement[] requirements = createRequired(requires);
		IRequirement[] metaRequirements = createRequired(metaRequires);
		ILicense[] licenses = new ILicense[] {MetadataFactory.createLicense(URI.create("http://eclipse.org"), "license text"), MetadataFactory.createLicense(URI.create("http://apache.org"), "license text2")};
		ITouchpointData tpData = createTouchpointData(instructions);
		IUpdateDescriptor update = createUpdateDescriptor();
		MetadataFactory.InstallableUnitDescription iu1 = new MetadataFactory.InstallableUnitDescription();
		iu1.setId(id);
		iu1.setVersion(version);
		iu1.setFilter(filter);
		iu1.setLicenses(licenses);
		IProvidedCapability[] provides1 = new IProvidedCapability[additionalProvides.length + 1];
		provides1[0] = getSelfCapability(id, version);
		for (int i = 0; i < additionalProvides.length; i++) {
			provides1[i + 1] = additionalProvides[i];
		}
		for (Entry<String, String> entry : propertyMap.entrySet()) {
			iu1.setProperty(entry.getKey(), entry.getValue());
		}
		iu1.setCapabilities(provides1);
		iu1.setRequirements(requirements);
		iu1.setTouchpointType(TOUCHPOINT_OSGI);
		if (tpData != null)
			iu1.addTouchpointData(tpData);
		iu1.setSingleton(false);
		iu1.setUpdateDescriptor(update);
		if (metaRequirements == null)
			metaRequirements = NO_REQUIRES;
		iu1.setMetaRequirements(metaRequirements);
		IInstallableUnit iu = MetadataFactory.createInstallableUnit(iu1);
		return iu;
	}

	public void testIUPatchPersistence() throws IOException {
		IInstallableUnit iu0 = createPatchIU();
		validateIU(iu0);
		try (ByteArrayOutputStream output0 = new ByteArrayOutputStream(3072)) {
			IUStringWriter writer0 = new IUStringWriter(output0);
			writer0.writeTest(iu0);
			String iuText0 = output0.toString();

			IUStringParser parser = new IUStringParser(TestActivator.context, TestActivator.PI_PROV_TESTS);
			parser.parse(iuText0);
			assertTrue("Error parsing test iu: " + parser.getStatus().getMessage(), parser.getStatus().isOK());
			InstallableUnitPatch iu1 = (InstallableUnitPatch) parser.getRootObject();
			validateIU(iu1);
			validateIUPatch(iu1);
			try (ByteArrayOutputStream output1 = new ByteArrayOutputStream(1492)) {
				IUStringWriter writer = new IUStringWriter(output1);
				writer.writeTest(iu1);
				String iuText1 = output1.toString();
				output1.close();
				assertTrue("Installable unit write after read after write produced different XML", iuText1.equals(iuText0));
			}
		}

	}

	public void testIUPatchPersistence2() throws IOException {
		IInstallableUnit iu0 = createPatchWithEmptyScope();
		validateIU(iu0);
		try (ByteArrayOutputStream output0 = new ByteArrayOutputStream(3072)) {
			IUStringWriter writer0 = new IUStringWriter(output0);
			writer0.writeTest(iu0);
			String iuText0 = output0.toString();

			IUStringParser parser = new IUStringParser(TestActivator.context, TestActivator.PI_PROV_TESTS);
			parser.parse(iuText0);
			assertTrue("Error parsing test iu: " + parser.getStatus().getMessage(), parser.getStatus().isOK());
			InstallableUnitPatch iu1 = (InstallableUnitPatch) parser.getRootObject();
			validateIU(iu1);
			validateIUPatchWithEmptyScope(iu1);
			try (ByteArrayOutputStream output1 = new ByteArrayOutputStream(1492)) {
				IUStringWriter writer = new IUStringWriter(output1);
				writer.writeTest(iu1);
			}
			//the content on disk is not the same but it is normal because a RequiredCapability array of RequiredCapability[0][0] is not persisted the same
			// than RequiredCapability[][] {{}}
			//assertTrue("Installable unit write after read after write produced different XML", iuText1.equals(iuText0));
		}

	}

	public void testIUPersistence() throws IOException {
		IInstallableUnit iu0 = createPersistenceTestIU();
		validateIU(iu0);
		try (ByteArrayOutputStream output0 = new ByteArrayOutputStream(3072)) {
			IUStringWriter writer0 = new IUStringWriter(output0);
			writer0.writeTest(iu0);
			String iuText0 = output0.toString();

			IUStringParser parser = new IUStringParser(TestActivator.context, TestActivator.PI_PROV_TESTS);
			parser.parse(iuText0);
			assertTrue("Error parsing test iu: " + parser.getStatus().getMessage(), parser.getStatus().isOK());
			InstallableUnit iu1 = (InstallableUnit) parser.getRootObject();
			validateIU(iu1);
			assertEquals(2, iu1.getLicenses().size());
			try (ByteArrayOutputStream output1 = new ByteArrayOutputStream(1492)) {
				IUStringWriter writer = new IUStringWriter(output1);
				writer.writeTest(iu1);
				String iuText1 = output1.toString();
				assertTrue("Installable unit write after read after write produced different XML", iuText1.equals(iuText0));
			}
		}
	}

	private void validateIU(IInstallableUnit iu) {
		assertTrue("Installable unit id is not correct", id.equals(iu.getId()));
		assertTrue("Installable unit version is not correct", version.equals(iu.getVersion()));
		assertTrue("Installable unit filter is not correct", filter.equals(iu.getFilter() == null ? null : iu.getFilter()));
		assertEquals("Installable unit properties are not correct", propertyMap, iu.getProperties());
		assertTrue("Installable unit provided capabilities are not correct", equal(addSelfCapability(iu, provides), extractProvides(iu)));
		assertTrue("Installable unit required capabilities are not correct", equal(requires, extractRequires(iu)));
		assertTrue("Installable unit meta required capabilities are not correct", equal(metaRequires, extractMetaRequires(iu)));
		assertTrue("Installable unit update descriptor are not correct", id.equals(RequiredCapability.extractName(iu.getUpdateDescriptor().getIUsBeingUpdated().iterator().next())));
		assertTrue("Installable unit update descriptor are not correct", IUpdateDescriptor.HIGH == iu.getUpdateDescriptor().getSeverity());
		assertTrue("Installable unit update descriptor are not correct", "desc".equals(iu.getUpdateDescriptor().getDescription()));
		assertTrue("Installable unit update descriptor are not correct", new VersionRange(IU_TEST_VERSION, true, IU_TEST_VERSION, true).equals(RequiredCapability.extractRange(iu.getUpdateDescriptor().getIUsBeingUpdated().iterator().next())));
	}

	private void validateIUPatch(IInstallableUnitPatch iu) {
		validateIU(iu);
		assertTrue(iu.getApplicabilityScope() != null);
		assertTrue(iu.getRequirements() != null);
		assertEquals(3, iu.getRequirementsChange().size());
		assertEquals(null, iu.getRequirementsChange().get(1).applyOn());
		assertNotNull(iu.getRequirementsChange().get(1).newValue());
		assertEquals(null, iu.getRequirementsChange().get(2).newValue());
		assertNotNull(iu.getRequirementsChange().get(2).applyOn());
		assertEquals(2, iu.getApplicabilityScope().length);
		assertEquals(2, iu.getApplicabilityScope()[0].length);
		assertEquals(1, iu.getApplicabilityScope()[1].length);
		assertNull(iu.getLifeCycle());
	}

	private void validateIUPatchWithEmptyScope(IInstallableUnitPatch iu) {
		validateIU(iu);
		assertTrue(iu.getApplicabilityScope() != null);
		assertTrue(iu.getRequirements() != null);
		assertEquals(3, iu.getRequirementsChange().size());
		assertEquals(null, iu.getRequirementsChange().get(1).applyOn());
		assertNotNull(iu.getRequirementsChange().get(1).newValue());
		assertEquals(null, iu.getRequirementsChange().get(2).newValue());
		assertNotNull(iu.getRequirementsChange().get(2).applyOn());
		assertEquals(0, iu.getApplicabilityScope().length);
		assertNull(iu.getLifeCycle());
	}

}
