/*******************************************************************************
 * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
 * Copyright (C) 2011, Mathias Kinzler <mathias.kinzler@sap.com>
 * Copyright (C) 2012, Robin Stocker <robin@nibor.org>
 * Copyright (C) 2015, Stephan Hackstedt <stephan.hackstedt@googlemail.com>
 * Copyright (C) 2016, 2022 Thomas Wolf <twolf@apache.org>
 *
 * All rights reserved. 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
 *******************************************************************************/
package org.eclipse.egit.core.op;

import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.text.MessageFormat;
import java.util.Collection;
import java.util.List;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.egit.core.Activator;
import org.eclipse.egit.core.EclipseGitProgressTransformer;
import org.eclipse.egit.core.internal.CoreText;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.CredentialsProvider;
import org.eclipse.jgit.transport.PushResult;
import org.eclipse.jgit.transport.RemoteConfig;
import org.eclipse.jgit.transport.RemoteRefUpdate;
import org.eclipse.jgit.transport.RemoteRefUpdate.Status;
import org.eclipse.jgit.transport.Transport;
import org.eclipse.jgit.transport.URIish;
import org.eclipse.jgit.util.SystemReader;
import org.eclipse.osgi.util.NLS;

/**
 * Push operation: pushing from local repository to one or many remote ones.
 */
public class PushOperation {

	private final Repository localDb;

	private final PushOperationSpecification specification;

	private final boolean dryRun;

	private final String remoteName;

	private final int timeout;

	private OutputStream out;

	private PushOperationResult operationResult;

	private CredentialsProvider credentialsProvider;

	/**
	 * Create push operation for provided specification.
	 *
	 * @param localDb
	 *            local repository.
	 * @param specification
	 *            specification of ref updates for remote repositories.
	 * @param dryRun
	 *            true if push operation should just check for possible result
	 *            and not really update remote refs, false otherwise - when push
	 *            should act normally.
	 * @param timeout
	 *            the timeout in seconds (0 for no timeout)
	 */
	public PushOperation(Repository localDb,
			PushOperationSpecification specification, boolean dryRun,
			int timeout) {
		this(localDb, null, specification, dryRun, timeout);
	}

	/**
	 * Creates a push operation for a remote configuration.
	 *
	 * @param localDb
	 * @param remoteName
	 * @param dryRun
	 * @param timeout
	 */
	public PushOperation(Repository localDb, String remoteName, boolean dryRun,
			int timeout) {
		this(localDb, remoteName, null, dryRun, timeout);
	}

	private PushOperation(Repository localDb, String remoteName,
			PushOperationSpecification specification, boolean dryRun,
			int timeout) {
		this.localDb = localDb;
		this.specification = specification;
		this.dryRun = dryRun;
		this.remoteName = remoteName;
		this.timeout = timeout;
	}

	/**
	 * Determines the RemoteConfig to use for a given branch.
	 *
	 * @param branch
	 *            short name of the branch to get the {@link RemoteConfig} for
	 * @param config
	 *            repository {@link Config} to use
	 * @return the {@link RemoteConfig}, or {@code null} if nothing is
	 *         configured
	 */
	public static RemoteConfig getRemote(String branch,
			Config config) {
		if (branch == null) {
			return null;
		}
		String defaultPushRemote = config.getString(
				ConfigConstants.CONFIG_REMOTE_SECTION, branch,
				ConfigConstants.CONFIG_KEY_PUSH_DEFAULT);
		String remoteName = null;
		if (!ObjectId.isId(branch)) {
			remoteName = config.getString(ConfigConstants.CONFIG_BRANCH_SECTION,
					branch, ConfigConstants.CONFIG_KEY_PUSH_REMOTE);
			if (remoteName == null) {
				if (defaultPushRemote != null) {
					remoteName = defaultPushRemote;
				} else {
					remoteName = config.getString(
							ConfigConstants.CONFIG_BRANCH_SECTION, branch,
							ConfigConstants.CONFIG_KEY_REMOTE);
				}
			}
		}
		if (defaultPushRemote == null) {
			defaultPushRemote = Constants.DEFAULT_REMOTE_NAME;
		}
		// check if we find the configured and default Remotes
		List<RemoteConfig> allRemotes;
		try {
			allRemotes = RemoteConfig.getAllRemoteConfigs(config);
		} catch (URISyntaxException e) {
			return null;
		}

		RemoteConfig defaultConfig = null;
		for (RemoteConfig cfg : allRemotes) {
			if (remoteName != null && cfg.getName().equals(remoteName)) {
				return cfg;
			} else if (cfg.getName().equals(defaultPushRemote)) {
				defaultConfig = cfg;
			} else if (defaultConfig == null
					&& cfg.getName().equals(Constants.DEFAULT_REMOTE_NAME)) {
				defaultConfig = cfg;
			}
		}

		return defaultConfig;
	}

	/**
	 * @param credentialsProvider
	 */
	public void setCredentialsProvider(CredentialsProvider credentialsProvider) {
		this.credentialsProvider = credentialsProvider;
	}

	/**
	 * @return the operation's credentials provider
	 */
	public CredentialsProvider getCredentialsProvider() {
		return credentialsProvider;
	}

	/**
	 * @return push operation result
	 */
	public PushOperationResult getOperationResult() {
		if (operationResult == null)
			throw new IllegalStateException(CoreText.OperationNotYetExecuted);
		return operationResult;
	}

	/**
	 * @return operation specification, as provided in constructor (may be
	 *         <code>null</code>)
	 */
	public PushOperationSpecification getSpecification() {
		return specification;
	}

	/**
	 * @param actMonitor
	 *            may be <code>null</code> if progress monitoring is not desired
	 * @throws InvocationTargetException
	 *             not really used: failure is communicated via the result (see
	 *             {@link #getOperationResult()})
	 */
	public void run(IProgressMonitor actMonitor)
			throws InvocationTargetException {

		if (operationResult != null)
			throw new IllegalStateException(CoreText.OperationAlreadyExecuted);

		if (this.specification != null)
			for (URIish uri : this.specification.getURIs()) {
				for (RemoteRefUpdate update : this.specification
						.getRefUpdates(uri))
					if (update.getStatus() != Status.NOT_ATTEMPTED)
						throw new IllegalStateException(
								CoreText.RemoteRefUpdateCantBeReused);
			}

		final int totalWork;
		if (specification != null) {
			totalWork = specification.getURIsNumber();
		} else {
			totalWork = 1;
		}

		String taskName = dryRun ? CoreText.PushOperation_taskNameDryRun
				: CoreText.PushOperation_taskNameNormalRun;
		SubMonitor progress = SubMonitor.convert(actMonitor, totalWork);
		progress.setTaskName(taskName);

		operationResult = new PushOperationResult();
		try (Git git = new Git(localDb)) {
			Charset hookCharset = SystemReader.getInstance()
					.getDefaultCharset();
			if (specification != null) {
				StringBuilder allHookOutputs = new StringBuilder();
				StringBuilder allHookErrors = new StringBuilder();
				for (final URIish uri : specification.getURIs()) {
					if (progress.isCanceled()) {
						operationResult.addOperationResult(uri,
								CoreText.PushOperation_resultCancelled);
						progress.worked(1);
						continue;
					}

					Collection<RemoteRefUpdate> refUpdates = specification
							.getRefUpdates(uri);
					final EclipseGitProgressTransformer gitSubMonitor = new EclipseGitProgressTransformer(
							progress.newChild(1));

					try (Transport transport = Transport.open(localDb, uri)) {
						transport.setDryRun(dryRun);
						transport.setTimeout(timeout);
						if (credentialsProvider != null) {
							transport.setCredentialsProvider(
									credentialsProvider);
						}
						try (ByteArrayOutputStream hookOutBytes = new ByteArrayOutputStream();
								ByteArrayOutputStream hookErrBytes = new ByteArrayOutputStream();
								PrintStream stdout = new PrintStream(hookOutBytes, true, hookCharset);
								PrintStream stderr = new PrintStream(hookErrBytes, true, hookCharset)) {
							transport.setHookOutputStream(stdout);
							transport.setHookErrorStream(stderr);
							PushResult result = transport.push(gitSubMonitor,
									refUpdates, out);
							stdout.flush();
							stderr.flush();
							addHookMessage(result.getURI(),
									hookOutBytes.toString(hookCharset),
									allHookOutputs);
							addHookMessage(result.getURI(),
									hookErrBytes.toString(hookCharset),
									allHookErrors);
							operationResult.addOperationResult(result.getURI(),
									result);
							specification.addURIRefUpdates(result.getURI(),
									result.getRemoteUpdates());
						}
					} catch (JGitInternalException e) {
						String errorMessage = e.getCause() != null
								? e.getCause().getMessage() : e.getMessage();
						String userMessage = NLS.bind(
								CoreText.PushOperation_InternalExceptionOccurredMessage,
								errorMessage);
						handleException(uri, e, userMessage);
					} catch (Exception e) {
						handleException(uri, e, e.getMessage());
					}
				}
				operationResult.setHookOutput(allHookOutputs.toString(),
						allHookErrors.toString());
			} else {
				final EclipseGitProgressTransformer gitMonitor = new EclipseGitProgressTransformer(
						progress.newChild(totalWork));
				try (ByteArrayOutputStream hookOutBytes = new ByteArrayOutputStream();
						ByteArrayOutputStream hookErrBytes = new ByteArrayOutputStream();
						PrintStream stdout = new PrintStream(hookOutBytes, true,
								hookCharset);
						PrintStream stderr = new PrintStream(hookErrBytes, true,
								hookCharset)) {
					Iterable<PushResult> results = git.push()
							.setRemote(remoteName)
							.setDryRun(dryRun)
							.setTimeout(timeout)
							.setProgressMonitor(gitMonitor)
							.setCredentialsProvider(credentialsProvider)
							.setOutputStream(out)
							.setHookOutputStream(stdout)
							.setHookErrorStream(stderr)
							.call();
					stdout.flush();
					stderr.flush();
					operationResult.setHookOutput(
							hookOutBytes.toString(hookCharset),
							hookErrBytes.toString(hookCharset));
					for (PushResult result : results) {
						operationResult.addOperationResult(result.getURI(),
								result);
					}
				} catch (JGitInternalException e) {
					String errorMessage = e.getCause() != null
							? e.getCause().getMessage() : e.getMessage();
					String userMessage = NLS.bind(
							CoreText.PushOperation_InternalExceptionOccurredMessage,
							errorMessage);
					URIish uri = getPushURIForErrorHandling();
					handleException(uri, e, userMessage);
				} catch (Exception e) {
					URIish uri = getPushURIForErrorHandling();
					handleException(uri, e, e.getMessage());
				}
			}
		}
	}

	private void addHookMessage(URIish uri, String msg, StringBuilder all) {
		if (!msg.isEmpty()) {
			if (all.length() > 0 && all.charAt(all.length() - 1) != '\n') {
				all.append('\n');
			}
			all.append(
					MessageFormat.format(CoreText.PushOperation_ForUri, uri));
			all.append('\n');
			all.append(msg);
		}
	}

	private void handleException(final URIish uri, Exception e,
			String userMessage) {
		String uriString;
		if (uri != null) {
			operationResult.addOperationResult(uri, userMessage);
			uriString = uri.toString();
		} else
			uriString = "retrieving URI failed"; //$NON-NLS-1$

		String userMessageForUri = NLS.bind(
				CoreText.PushOperation_ExceptionOccurredDuringPushOnUriMessage,
				uriString, userMessage);
		Activator.logError(userMessageForUri, e);
	}

	private URIish getPushURIForErrorHandling() {
		RemoteConfig rc = null;
		try {
			rc = new RemoteConfig(localDb.getConfig(), remoteName);
			return rc.getPushURIs().isEmpty() ? rc.getURIs().get(0) : rc
					.getPushURIs().get(0);
		} catch (URISyntaxException e) {
			// should not happen
			Activator.logError("Reading RemoteConfig failed", e); //$NON-NLS-1$
			return null;
		}
	}

	/**
	 * Sets the output stream this operation will write sideband messages to.
	 *
	 * @param out
	 *            the outputstream to write to
	 * @since 3.0
	 */
	public void setOutputStream(OutputStream out) {
		this.out = out;
	}
}
