/*********************************************************************
 * Copyright (c) 2010, 2013 Sony Ericsson/ST Ericsson 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:
 *      Sony Ericsson/ST Ericsson - initial API and implementation
 *      Tasktop Technologies - improvements
 *      GitHub, Inc. - fixes for bug 354753
 *      Sascha Scholz (SAP) - improvements
 *      Francois Chouinard (Ericsson) - Bug 414253 Add support for Gerrit Dashboard
 *      Jacques Bouthillier (Ericsson) - Bug 414253 Add support for Gerrit Dashboard
 *      Jacques Bouthillier (Ericsson) - Bug 426505 Add Starred functionality
 *********************************************************************/
package org.eclipse.mylyn.internal.gerrit.core;

import java.net.UnknownHostException;
import java.util.Calendar;
import java.util.Date;
import java.util.EnumSet;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.lang.StringUtils;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.mylyn.commons.core.StatusHandler;
import org.eclipse.mylyn.commons.net.Policy;
import org.eclipse.mylyn.internal.gerrit.core.client.GerritAuthenticationState;
import org.eclipse.mylyn.internal.gerrit.core.client.GerritCapabilities;
import org.eclipse.mylyn.internal.gerrit.core.client.GerritClient;
import org.eclipse.mylyn.internal.gerrit.core.client.GerritClientStateListener;
import org.eclipse.mylyn.internal.gerrit.core.client.GerritConfiguration;
import org.eclipse.mylyn.internal.gerrit.core.client.GerritException;
import org.eclipse.mylyn.internal.gerrit.core.client.GerritHttpException;
import org.eclipse.mylyn.internal.gerrit.core.client.GerritLoginException;
import org.eclipse.mylyn.internal.gerrit.core.client.GerritSystemInfo;
import org.eclipse.mylyn.internal.gerrit.core.client.JSonSupport;
import org.eclipse.mylyn.internal.gerrit.core.client.data.GerritQueryResult;
import org.eclipse.mylyn.reviews.core.model.ReviewStatus;
import org.eclipse.mylyn.reviews.core.spi.ReviewsConnector;
import org.eclipse.mylyn.tasks.core.IRepositoryQuery;
import org.eclipse.mylyn.tasks.core.ITask;
import org.eclipse.mylyn.tasks.core.ITaskMapping;
import org.eclipse.mylyn.tasks.core.RepositoryStatus;
import org.eclipse.mylyn.tasks.core.TaskRepository;
import org.eclipse.mylyn.tasks.core.TaskRepositoryLocationFactory;
import org.eclipse.mylyn.tasks.core.data.AbstractTaskDataHandler;
import org.eclipse.mylyn.tasks.core.data.TaskData;
import org.eclipse.mylyn.tasks.core.data.TaskDataCollector;
import org.eclipse.mylyn.tasks.core.data.TaskMapper;
import org.eclipse.mylyn.tasks.core.sync.ISynchronizationSession;
import org.eclipse.osgi.util.NLS;

import com.google.gwtorm.client.KeyUtil;
import com.google.gwtorm.server.StandardKeyEncoder;

/**
 * The Gerrit connector core.
 * 
 * @author Mikael Kober
 * @author Thomas Westling
 * @author Sascha Scholz
 * @author Miles Parker
 * @author Francois Chouinard
 * @author Jacques Bouthillier
 */
public class GerritConnector extends ReviewsConnector {

	static Logger logger = Logger.getLogger("com.google.gson.ParameterizedTypeHandlerMap"); //$NON-NLS-1$

	static {
		KeyUtil.setEncoderImpl(new StandardKeyEncoder());
		// disable logging of Overriding the existing type handler for class java.sql.Timestamp message
		logger.setLevel(Level.OFF);
	}

	private static final Pattern CHANGE_ID_PATTERN = Pattern.compile("(/#change,|/#/c/)(\\d+)"); //$NON-NLS-1$

	/**
	 * Prefix for task id in a task-url: http://[gerrit-repository]/#change,[task.id] for Gerrit 2.1.
	 */
	public static final String CHANGE_PREFIX_OLD = "/#change,"; //$NON-NLS-1$

	/**
	 * Prefix for task id in a task-url: http://[gerrit-repository]/#/c/[task.id] for Gerrit 2.2 and later.
	 */
	public static final String CHANGE_PREFIX_NEW = "/#/c/"; //$NON-NLS-1$

	/**
	 * Connector kind
	 */
	public static final String CONNECTOR_KIND = "org.eclipse.mylyn.gerrit"; //$NON-NLS-1$

	public static final String KEY_REPOSITORY_CONFIG = CONNECTOR_KIND + ".config"; //$NON-NLS-1$

	public static final String KEY_REPOSITORY_AUTH = CONNECTOR_KIND + ".auth"; //$NON-NLS-1$

	public static final String KEY_REPOSITORY_ACCOUNT_ID = CONNECTOR_KIND + ".accountId"; //$NON-NLS-1$

	public static final String KEY_REPOSITORY_OPEN_ID_ENABLED = CONNECTOR_KIND + ".openId.enabled"; //$NON-NLS-1$

	public static final String KEY_REPOSITORY_OPEN_ID_PROVIDER = CONNECTOR_KIND + ".openId.provider"; //$NON-NLS-1$

	public static final String GERRIT_RPC_URI = "/gerrit/rpc/"; //$NON-NLS-1$

	public static final String GERRIT_260_RPC_URI = "/gerrit_ui/rpc/"; //$NON-NLS-1$

	private final GerritTaskDataHandler taskDataHandler = new GerritTaskDataHandler(this);

	private TaskRepositoryLocationFactory taskRepositoryLocationFactory = new TaskRepositoryLocationFactory();

	private final ConcurrentMap<TaskRepository, GerritConfiguration> configurationCache = new ConcurrentHashMap<TaskRepository, GerritConfiguration>();

	public GerritConnector() {
		if (GerritCorePlugin.getDefault() != null) {
			GerritCorePlugin.getDefault().setConnector(this);
		}
	}

	/**
	 * Not supported, yet.
	 */
	@Override
	public boolean canCreateNewTask(TaskRepository arg0) {
		return false;
	}

	@Override
	public boolean canCreateTaskFromKey(TaskRepository arg0) {
		return true;
	}

	public GerritClient getClient(TaskRepository repository) {
		return (GerritClient) getReviewClient(repository);
	}

	@Override
	public String getConnectorKind() {
		return CONNECTOR_KIND;
	}

	@Override
	public String getLabel() {
		return NLS.bind(Messages.GerritConnector_Label, GerritCapabilities.MINIMUM_SUPPORTED_VERSION,
				GerritCapabilities.MAXIMUM_SUPPORTED_VERSION);
	}

	@Override
	public TaskData getTaskData(TaskRepository repository, String taskId, IProgressMonitor monitor)
			throws CoreException {
		return taskDataHandler.getTaskData(repository, taskId, monitor);
	}

	@Override
	public AbstractTaskDataHandler getTaskDataHandler() {
		return taskDataHandler;
	}

	@Override
	public String getRepositoryUrlFromTaskUrl(String url) {
		if (url == null) {
			return null;
		}

		int i = url.indexOf(CHANGE_PREFIX_OLD);
		if (i != -1) {
			return url.substring(0, i);
		}

		i = url.indexOf(CHANGE_PREFIX_NEW);
		if (i != -1) {
			return url.substring(0, i);
		}

		return null;
	}

	@Override
	public String getTaskIdFromTaskUrl(String url) {
		if (url == null) {
			return null;
		}

		// example: https://review.sonyericsson.net/#change,14175
		// example: https://review.sonyericsson.net/#/c/14175
		Matcher matcher = CHANGE_ID_PATTERN.matcher(url);
		if (matcher.find()) {
			return matcher.group(2);
		}

		return null;
	}

	@Override
	public ITaskMapping getTaskMapping(TaskData taskData) {
		return new TaskMapper(taskData);
	}

	public synchronized TaskRepositoryLocationFactory getTaskRepositoryLocationFactory() {
		return taskRepositoryLocationFactory;
	}

	@Override
	public String getTaskUrl(String repositoryUrl, String taskId) {
		repositoryUrl = StringUtils.removeEnd(repositoryUrl, "/"); //$NON-NLS-1$
		return repositoryUrl + CHANGE_PREFIX_NEW + taskId + "/"; //$NON-NLS-1$
	}

	@Override
	public boolean hasTaskChanged(TaskRepository repository, ITask task, TaskData taskData) {
		ITaskMapping taskMapping = getTaskMapping(taskData);
		Date repositoryDate = taskMapping.getModificationDate();
		Date localDate = task.getModificationDate();
		if (areMillisecondsMissingFromLocalDate(localDate, repositoryDate)) {
			return false;
		}
		return repositoryDate == null || !repositoryDate.equals(localDate);
	}

	protected boolean areMillisecondsMissingFromLocalDate(Date localDate, Date repositoryDate) {
		if (localDate == null || repositoryDate == null) {
			return false;
		}
		Calendar repositoryCalendar = Calendar.getInstance();
		repositoryCalendar.setTime(repositoryDate);
		Calendar localCalendar = Calendar.getInstance();
		localCalendar.setTime(localDate);
		return localCalendar.get(Calendar.MILLISECOND) == 0 && repositoryCalendar.get(Calendar.MILLISECOND) != 0
				&& Math.abs(repositoryCalendar.getTimeInMillis() - localCalendar.getTimeInMillis()) < 1000;
	}

	@Override
	public IStatus performQuery(TaskRepository repository, IRepositoryQuery query, TaskDataCollector resultCollector,
			ISynchronizationSession session, IProgressMonitor monitor) {
		try {
			monitor.beginTask(Messages.GerritConnector_Executing_query, IProgressMonitor.UNKNOWN);
			GerritClient client = getClient(repository);
			client.refreshConfigOnce(monitor);

			List<GerritQueryResult> result = null;
			if (GerritQuery.ALL_OPEN_CHANGES.equals(query.getAttribute(GerritQuery.TYPE))) {
				result = client.queryAllReviews(monitor);
			} else if (GerritQuery.MY_CHANGES.equals(query.getAttribute(GerritQuery.TYPE))) {
				result = client.queryMyReviews(monitor);
			} else if (GerritQuery.MY_WATCHED_CHANGES.equals(query.getAttribute(GerritQuery.TYPE))) {
				result = client.queryWatchedReviews(monitor);
			} else if (GerritQuery.CUSTOM.equals(query.getAttribute(GerritQuery.TYPE))) {
				String queryString = query.getAttribute(GerritQuery.QUERY_STRING);
				result = client.executeQuery(monitor, queryString);
			} else if (GerritQuery.OPEN_CHANGES_BY_PROJECT.equals(query.getAttribute(GerritQuery.TYPE))) {
				String project = query.getAttribute(GerritQuery.PROJECT);
				result = client.queryByProject(monitor, project);
			} else {
				String queryString = query.getAttribute(GerritQuery.QUERY_STRING);
				if (StringUtils.isNotBlank(queryString)) {
					result = client.executeQuery(monitor, queryString);
				}
			}

			if (result != null) {
				for (GerritQueryResult changeInfo : result) {
					TaskData taskData = taskDataHandler.createPartialTaskData(repository,
							Integer.toString(changeInfo.getNumber()), monitor);
					taskDataHandler.updatePartialTaskData(repository, taskData, changeInfo);
					if (monitor.isCanceled()) {
						break;
					}

					resultCollector.accept(taskData);
				}
				return Status.OK_STATUS;
			}

			return new Status(IStatus.ERROR, GerritCorePlugin.PLUGIN_ID, NLS.bind("Unknown query type: {0}", //$NON-NLS-1$
					query.getAttribute(GerritQuery.PROJECT)));
		} catch (UnsupportedClassVersionError e) {
			return toStatus(repository, e);
		} catch (GerritException e) {
			return toStatus(repository, "Problem performing query", e); //$NON-NLS-1$
		} finally {
			monitor.done();
		}
	}

	public synchronized void setTaskRepositoryLocationFactory(
			TaskRepositoryLocationFactory taskRepositoryLocationFactory) {
		this.taskRepositoryLocationFactory = taskRepositoryLocationFactory;
	}

	@Override
	public void updateRepositoryConfiguration(TaskRepository repository, IProgressMonitor monitor) throws CoreException {
		try {
			getClient(repository).refreshConfig(monitor);
		} catch (GerritException e) {
			throw toCoreException(repository, "Problem updating repository", e); //$NON-NLS-1$
		}
	}

	@Override
	public void updateTaskFromTaskData(TaskRepository taskRepository, ITask task, TaskData taskData) {
		Date oldModificationDate = task.getModificationDate();

		TaskMapper mapper = (TaskMapper) getTaskMapping(taskData);
		mapper.applyTo(task);
		String key = task.getTaskKey();
		if (key != null) {
			task.setSummary(NLS.bind("{0} [{1}]", mapper.getSummary(), key)); //$NON-NLS-1$
			task.setTaskKey(task.getTaskId());
		}

		// retain modification date to force an update when full task data is received
		if (taskData.isPartial()) {
			task.setModificationDate(oldModificationDate);
		}
	}

	public GerritSystemInfo validate(TaskRepository repository, IProgressMonitor monitor) throws CoreException {
		// only allow user prompting in case of Open ID authentication
		if (!Boolean.parseBoolean(repository.getProperty(GerritConnector.KEY_REPOSITORY_OPEN_ID_ENABLED))) {
			monitor = Policy.backgroundMonitorFor(monitor);
		}
		try {
			return createTransientReviewClient(repository).getInfo(monitor);
		} catch (UnsupportedClassVersionError e) {
			throw toCoreException(repository, e);
		} catch (GerritException e) {
			throw toCoreException(repository, "Invalid repository", e); //$NON-NLS-1$
		}
	}

	@Override
	protected GerritClient createReviewClient(final TaskRepository repository, boolean b) {
		GerritConfiguration config = loadConfiguration(repository);
		GerritAuthenticationState authState = loadAuthState(repository);
		return GerritClient.create(repository, taskRepositoryLocationFactory.createWebLocation(repository), config,
				authState, null, new GerritClientStateListener() {
					@Override
					protected void configurationChanged(GerritConfiguration config) {
						saveConfiguration(repository, config);
					}

					@Override
					protected void authStateChanged(GerritAuthenticationState authState) {
						repository.setProperty(KEY_REPOSITORY_AUTH, authStateToString(authState));
					}
				});
	}

	private static String authStateToString(GerritAuthenticationState authState) {
		if (authState == null) {
			return null;
		}
		try {
			JSonSupport support = new JSonSupport();
			return support.toJson(authState);
		} catch (Exception e) {
			// ignore
			return null;
		}
	}

	protected GerritClient createTransientReviewClient(final TaskRepository repository) {
		return GerritClient.create(repository, taskRepositoryLocationFactory.createWebLocation(repository));
	}

	private GerritAuthenticationState loadAuthState(final TaskRepository repository) {
		String authState = repository.getProperty(KEY_REPOSITORY_AUTH);
		if (authState != null) {
			return authStateFromString(authState);
		}
		return null;
	}

	private static GerritAuthenticationState authStateFromString(String token) {
		try {
			JSonSupport support = new JSonSupport();
			return support.parseResponse(token, GerritAuthenticationState.class);
		} catch (Exception e) {
			// ignore
			return null;
		}
	}

	protected GerritConfiguration loadConfiguration(TaskRepository repository) {
		GerritConfiguration configuration = configurationCache.get(repository);
		if (configuration == null) {
			configuration = configurationFromString(repository.getProperty(KEY_REPOSITORY_CONFIG));
			if (configuration != null) {
				configurationCache.put(repository, configuration);
			}
		}
		return configuration;
	}

	protected void saveConfiguration(TaskRepository repository, GerritConfiguration configuration) {
		configurationCache.put(repository, configuration);
		repository.setProperty(KEY_REPOSITORY_CONFIG, configurationToString(configuration));
	}

	public GerritConfiguration getConfiguration(TaskRepository repository) {
		GerritConfiguration configuration = configurationCache.get(repository);
		if (configuration == null) {
			configuration = loadConfiguration(repository);
		}
		return configuration;
	}

	private static GerritConfiguration configurationFromString(String token) {
		if (token == null) {
			return null;
		}
		try {
			JSonSupport support = new JSonSupport();
			return support.parseResponse(token, GerritConfiguration.class);
		} catch (Exception e) {
			StatusHandler.log(new Status(IStatus.ERROR, GerritCorePlugin.PLUGIN_ID,
					"Failed to deserialize configuration: '" + token + "'", e)); //$NON-NLS-1$ //$NON-NLS-2$
			return null;
		}
	}

	private static String configurationToString(GerritConfiguration config) {
		try {
			JSonSupport support = new JSonSupport();
			return support.toJson(config);
		} catch (Exception e) {
			StatusHandler.log(new Status(IStatus.ERROR, GerritCorePlugin.PLUGIN_ID,
					"Failed to serialize configuration", e)); //$NON-NLS-1$
			return null;
		}
	}

	public CoreException toCoreException(TaskRepository repository, String qualifier, GerritException e) {
		return new CoreException(toStatus(repository, qualifier, e));
	}

	public static CoreException toCoreException(TaskRepository repository, UnsupportedClassVersionError e) {
		return new CoreException(toStatus(repository, e));
	}

	Status toStatus(TaskRepository repository, String qualifier, Exception e) {
		if (StringUtils.isEmpty(qualifier)) {
			qualifier = ""; //$NON-NLS-1$
		} else if (!StringUtils.endsWith(qualifier, ": ")) { //$NON-NLS-1$
			qualifier += ": "; //$NON-NLS-1$
		}
		if (e instanceof GerritHttpException) {
			int code = ((GerritHttpException) e).getResponseCode();
			return createErrorStatus(repository, qualifier + HttpStatus.getStatusText(code));
		} else if (e instanceof GerritLoginException) {
			if (repository != null) {
				return RepositoryStatus.createLoginError(repository.getUrl(), GerritCorePlugin.PLUGIN_ID);
			} else {
				return createErrorStatus(null, qualifier + "Unknown Host"); //$NON-NLS-1$
			}
		} else if (e instanceof UnknownHostException) {
			return createErrorStatus(repository, qualifier + "Unknown Host"); //$NON-NLS-1$
		} else if (e instanceof GerritException && e.getCause() != null) {
			Throwable cause = e.getCause();
			if (cause instanceof Exception) {
				return toStatus(repository, qualifier, (Exception) cause);
			}
		} else if (e instanceof GerritException && e.getMessage() != null) {
			return createErrorStatus(repository, NLS.bind("{0}Gerrit connection issue: {1}", qualifier, e.getMessage())); //$NON-NLS-1$
		}
		String message = NLS.bind("{0}Unexpected error while connecting to Gerrit: {1}", qualifier, e.getMessage()); //$NON-NLS-1$
		if (repository != null) {
			return RepositoryStatus.createStatus(repository, IStatus.ERROR, GerritCorePlugin.PLUGIN_ID, message);
		} else {
			return createErrorStatus(repository, message);
		}
	}

	protected Status createErrorStatus(TaskRepository repository, String message) {
		if (repository != null) {
			return RepositoryStatus.createStatus(repository, IStatus.ERROR, GerritCorePlugin.PLUGIN_ID, message);
		} else {
			return new Status(IStatus.ERROR, GerritCorePlugin.PLUGIN_ID, message + " (Repository Unknown)"); //$NON-NLS-1$
		}
	}

	public static Status toStatus(TaskRepository repository, UnsupportedClassVersionError e) {
		String message = NLS.bind("The Gerrit Connector requires at Java 1.6 or higer (installed version: {0})", //$NON-NLS-1$
				System.getProperty("java.version")); //$NON-NLS-1$
		return new Status(IStatus.ERROR, GerritCorePlugin.PLUGIN_ID, message, e);
	}

	public static boolean isClosed(String status) {
		return EnumSet.of(ReviewStatus.MERGED, ReviewStatus.ABANDONED).contains(ReviewStatus.get(status));
	}

	public void setStarred(TaskRepository taskRepository, String taskID, boolean starred,
			IProgressMonitor progressMonitor) throws CoreException {
		GerritClient client = getClient(taskRepository);
		try {
			client.setStarred(taskID, starred, progressMonitor);
		} catch (GerritException e) {
			throw toCoreException(e);
		}
	}

	private CoreException toCoreException(GerritException e) {
		return new CoreException(new Status(IStatus.ERROR, GerritCorePlugin.PLUGIN_ID,
				"Unable to set the starred flag, the following Status is received", e)); //$NON-NLS-1$
	}
}
