/*********************************************************************
 * 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.GerritClient;
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$

	/**
	 * Label for the connector.
	 */
	public static final String CONNECTOR_LABEL = "Gerrit Code Review"; //$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 Messages.GerritConnector_Label;
	}

	@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.updateTaskData(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 new GerritClient(repository, taskRepositoryLocationFactory.createWebLocation(repository), config,
				authState) {
			@Override
			protected void configurationChanged(GerritConfiguration config) {
				saveConfiguration(repository, config);
			}

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

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

	private GerritAuthenticationState loadAuthState(final TaskRepository repository) {
		String authState = repository.getProperty(KEY_REPOSITORY_AUTH);
		if (authState != null) {
			return GerritClient.authStateFromString(authState);
		}
		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$
	}
}
