/*******************************************************************************
 * Copyright (c) 2008, 2017 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
 *     Landmark Graphics Corporation - bug 397183
 *******************************************************************************/
package org.eclipse.equinox.internal.p2.touchpoint.natives.actions;

import java.io.File;
import java.io.IOException;
import java.util.Map;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.p2.engine.Profile;
import org.eclipse.equinox.internal.p2.touchpoint.natives.*;
import org.eclipse.equinox.p2.engine.spi.ProvisioningAction;
import org.eclipse.equinox.p2.engine.spi.Value;
import org.eclipse.equinox.p2.metadata.IArtifactKey;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.osgi.util.NLS;

public class UnzipAction extends ProvisioningAction {

	public static final String ACTION_UNZIP = "unzip"; //$NON-NLS-1$
	private Value<String[]> result;

	@Override
	public IStatus execute(Map<String, Object> parameters) {
		return unzip(parameters, true);
	}

	@Override
	public IStatus undo(Map<String, Object> parameters) {
		return CleanupzipAction.cleanupzip(parameters, false);
	}

	/**
	 * Unzip as directed by parameters.
	 * Record what was zipped in the profile.
	 *
	 * @param parameters
	 * @param restoreable - if the unzip should be backed up
	 * @return status
	 */
	public IStatus unzip(Map<String, Object> parameters, boolean restoreable) {
		String source = (String) parameters.get(ActionConstants.PARM_SOURCE);
		if (source == null) {
			return Util.createError(NLS.bind(Messages.param_not_set, ActionConstants.PARM_SOURCE, ACTION_UNZIP));
		}

		String originalSource = source;
		String target = (String) parameters.get(ActionConstants.PARM_TARGET);
		if (target == null) {
			return Util.createError(NLS.bind(Messages.param_not_set, ActionConstants.PARM_TARGET, ACTION_UNZIP));
		}

		IInstallableUnit iu = (IInstallableUnit) parameters.get(ActionConstants.PARM_IU);
		Profile profile = (Profile) parameters.get(ActionConstants.PARM_PROFILE);

		if (source.equals(ActionConstants.PARM_AT_ARTIFACT)) {
			String artifactLocation = (String) parameters.get(NativeTouchpoint.PARM_ARTIFACT_LOCATION);
			if (artifactLocation == null) {
				IArtifactKey artifactKey = (IArtifactKey) parameters.get(NativeTouchpoint.PARM_ARTIFACT);
				return Util.createError(NLS.bind(Messages.artifact_not_available, artifactKey));
			}
			source = artifactLocation;
		}
		IBackupStore store = restoreable ? (IBackupStore) parameters.get(NativeTouchpoint.PARM_BACKUP) : null;

		String path = (String) parameters.get(ActionConstants.PARM_PATH);
		String includePattern = (String) parameters.get(ActionConstants.PARM_INCLUDE);
		String excludePattern = (String) parameters.get(ActionConstants.PARM_EXCLUDE);

		File[] unzippedFiles = unzip(source, target, path, includePattern, excludePattern, store);
		String[] filesAsString = new String[unzippedFiles.length];
		for (int i = 0; i < unzippedFiles.length; i++) {
			filesAsString[i] = unzippedFiles[i].getAbsolutePath();
		}
		result = new Value<>(filesAsString);

		StringBuffer unzippedFileNameBuffer = new StringBuffer();
		for (File unzippedFile : unzippedFiles) {
			unzippedFileNameBuffer.append(unzippedFile.getAbsolutePath()).append(ActionConstants.PIPE);
		}

		profile.setInstallableUnitProperty(iu,
				"unzipped" + ActionConstants.PIPE + originalSource + ActionConstants.PIPE + target, //$NON-NLS-1$
				unzippedFileNameBuffer.toString());

		return Status.OK_STATUS;
	}

	/**
	 * Unzips a source zip into the given destination. Any existing contents in the destination
	 * are backed up in the provided backup store.
	 */
	private static File[] unzip(String source, String destination, String path, String includePattern,
			String excludePattern, IBackupStore store) {
		File zipFile = new File(source);
		if (zipFile == null || !zipFile.exists()) {
			Util.logError(UnzipAction.class.getName() + " the files to be unzipped is not here", null); //$NON-NLS-1$
		}
		try {
			String taskName = NLS.bind(Messages.unzipping, source);
			String[] includes = includePattern == null ? null : includePattern.split("\\s+"); //$NON-NLS-1$
			String[] excludes = excludePattern == null ? null : excludePattern.split("\\s+"); //$NON-NLS-1$
			return Util.unzipFile(zipFile, new File(destination), path, includes, excludes, store, taskName,
					new NullProgressMonitor());
		} catch (IOException e) {
			Util.logError(
					UnzipAction.class.getName() + " error unzipping zipfile: " + zipFile.getAbsolutePath() //$NON-NLS-1$
							+ "destination: " + destination, //$NON-NLS-1$
					null);
		}
		return new File[0];
	}

	@Override
	public Value<String[]> getResult() {
		return result;
	}
}