/*******************************************************************************
 * Copyright (c) 2004, 2010 Tasktop Technologies 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:
 *     Tasktop Technologies - initial API and implementation
 *******************************************************************************/

package org.eclipse.mylyn.internal.bugzilla.core;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.MessageFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.mylyn.commons.core.StatusHandler;
import org.eclipse.mylyn.commons.net.Policy;
import org.eclipse.mylyn.internal.tasks.core.AbstractTask;
import org.eclipse.mylyn.internal.tasks.core.RepositoryQuery;
import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector;
import org.eclipse.mylyn.tasks.core.IRepositoryQuery;
import org.eclipse.mylyn.tasks.core.ITask;
import org.eclipse.mylyn.tasks.core.ITask.PriorityLevel;
import org.eclipse.mylyn.tasks.core.RepositoryStatus;
import org.eclipse.mylyn.tasks.core.TaskRepository;
import org.eclipse.mylyn.tasks.core.data.AbstractTaskAttachmentHandler;
import org.eclipse.mylyn.tasks.core.data.AbstractTaskDataHandler;
import org.eclipse.mylyn.tasks.core.data.TaskAttribute;
import org.eclipse.mylyn.tasks.core.data.TaskAttributeMapper;
import org.eclipse.mylyn.tasks.core.data.TaskData;
import org.eclipse.mylyn.tasks.core.data.TaskDataCollector;
import org.eclipse.mylyn.tasks.core.data.TaskHistory;
import org.eclipse.mylyn.tasks.core.data.TaskMapper;
import org.eclipse.mylyn.tasks.core.data.TaskRelation;
import org.eclipse.mylyn.tasks.core.data.TaskRevision;
import org.eclipse.mylyn.tasks.core.sync.ISynchronizationSession;

/**
 * @author Mik Kersten
 * @author Rob Elves
 */
public class BugzillaRepositoryConnector extends AbstractRepositoryConnector {

	private static final String BUG_ID = "&bug_id="; //$NON-NLS-1$

	private static final String CHANGED_BUGS_CGI_ENDDATE = "&chfieldto=Now"; //$NON-NLS-1$

	private static final String CHANGED_BUGS_CGI_QUERY = "/buglist.cgi?query_format=advanced&chfieldfrom="; //$NON-NLS-1$

	private static final String CLIENT_LABEL = Messages.BugzillaRepositoryConnector_BUGZILLA_CONNECTOR_LABEL;

	private static final String COMMENT_FORMAT = "yyyy-MM-dd HH:mm"; //$NON-NLS-1$

	//private static final String DEADLINE_FORMAT = "yyyy-MM-dd"; //$NON-NLS-1$

	private static final String TIMESTAMP_WITH_OFFSET = "yyyy-MM-dd HH:mm:ss Z"; //$NON-NLS-1$

	private static final long HOUR = 1000 * 60 * 60;

	private final BugzillaTaskAttachmentHandler attachmentHandler = new BugzillaTaskAttachmentHandler(this);

	private final BugzillaTaskDataHandler taskDataHandler = new BugzillaTaskDataHandler(this);

	protected BugzillaClientManager clientManager;

	protected static BugzillaLanguageSettings enSetting;

	protected static final Set<BugzillaLanguageSettings> languages = new LinkedHashSet<BugzillaLanguageSettings>();

	private static final String ERROR_DELETING_CONFIGURATION = "Error removing corrupt repository configuration file."; //$NON-NLS-1$

	private static final String ERROR_INCOMPATIBLE_CONFIGURATION = "Reset Bugzilla repository configuration cache due to format change"; //$NON-NLS-1$

	private boolean cacheFileRead;

	private File repositoryConfigurationFile;

	private final Map<String, RepositoryConfiguration> repositoryConfigurations = new HashMap<String, RepositoryConfiguration>();

	// A Map from Java's  Platform to Buzilla's
	private static final Map<String, String> java2buzillaPlatformMap = new HashMap<String, String>();

	static {
		enSetting = new BugzillaLanguageSettings(IBugzillaConstants.DEFAULT_LANG);
		enSetting.addLanguageAttribute("error_login", "Login"); //$NON-NLS-1$ //$NON-NLS-2$
		enSetting.addLanguageAttribute("error_login", "log in"); //$NON-NLS-1$ //$NON-NLS-2$
		enSetting.addLanguageAttribute("error_login", "check e-mail"); //$NON-NLS-1$ //$NON-NLS-2$
		enSetting.addLanguageAttribute("error_login", "Invalid Username Or Password"); //$NON-NLS-1$ //$NON-NLS-2$
		enSetting.addLanguageAttribute("error_login", "account locked"); //$NON-NLS-1$//$NON-NLS-2$
		enSetting.addLanguageAttribute("error_collision", "Mid-air collision!"); //$NON-NLS-1$ //$NON-NLS-2$
		enSetting.addLanguageAttribute("error_comment_required", "Comment Required"); //$NON-NLS-1$ //$NON-NLS-2$
		enSetting.addLanguageAttribute("error_logged_out", "logged out"); //$NON-NLS-1$ //$NON-NLS-2$
		enSetting.addLanguageAttribute("bad_login", "Login"); //$NON-NLS-1$ //$NON-NLS-2$
		enSetting.addLanguageAttribute("bad_login", "log in"); //$NON-NLS-1$ //$NON-NLS-2$
		enSetting.addLanguageAttribute("bad_login", "check e-mail"); //$NON-NLS-1$ //$NON-NLS-2$
		enSetting.addLanguageAttribute("bad_login", "Invalid Username Or Password"); //$NON-NLS-1$ //$NON-NLS-2$
		enSetting.addLanguageAttribute("bad_login", "account locked"); //$NON-NLS-1$//$NON-NLS-2$
		enSetting.addLanguageAttribute("bad_login", "error"); //$NON-NLS-1$ //$NON-NLS-2$
		enSetting.addLanguageAttribute("processed", "processed"); //$NON-NLS-1$ //$NON-NLS-2$
		enSetting.addLanguageAttribute("changes_submitted", "Changes submitted"); //$NON-NLS-1$ //$NON-NLS-2$
		enSetting.addLanguageAttribute("changes_submitted", "added to Bug"); //$NON-NLS-1$ //$NON-NLS-2$
		enSetting.addLanguageAttribute("bug", "Bug"); //$NON-NLS-1$ //$NON-NLS-2$
		enSetting.addLanguageAttribute("bug", "Issue"); //$NON-NLS-1$ //$NON-NLS-2$
		enSetting.addLanguageAttribute("submitted", "Submitted"); //$NON-NLS-1$ //$NON-NLS-2$
		enSetting.addLanguageAttribute("submitted", "posted"); //$NON-NLS-1$ //$NON-NLS-2$
		enSetting.addLanguageAttribute("suspicious_action", "Suspicious action"); //$NON-NLS-1$ //$NON-NLS-2$
		enSetting.addLanguageAttribute("error_confirm_match", "confirm match"); //$NON-NLS-1$//$NON-NLS-2$
		enSetting.addLanguageAttribute("error_match_failed", "match failed"); //$NON-NLS-1$ //$NON-NLS-2$
		languages.add(enSetting);

		java2buzillaPlatformMap.put("x86", "PC"); // can be PC or Macintosh! //$NON-NLS-1$ //$NON-NLS-2$
		java2buzillaPlatformMap.put("x86_64", "PC"); //$NON-NLS-1$ //$NON-NLS-2$
		java2buzillaPlatformMap.put("ia64", "PC"); //$NON-NLS-1$ //$NON-NLS-2$
		java2buzillaPlatformMap.put("ia64_32", "PC"); //$NON-NLS-1$ //$NON-NLS-2$
		java2buzillaPlatformMap.put("sparc", "Sun"); //$NON-NLS-1$ //$NON-NLS-2$
		java2buzillaPlatformMap.put("ppc", "Power PC"); // not Power! //$NON-NLS-1$ //$NON-NLS-2$
	}

	public BugzillaRepositoryConnector() {
		if (BugzillaCorePlugin.getDefault() != null) {
			BugzillaCorePlugin.getDefault().setConnector(this);
			IPath path = BugzillaCorePlugin.getDefault().getConfigurationCachePath();
			this.repositoryConfigurationFile = path.toFile();
		}
	}

	public BugzillaRepositoryConnector(File repositoryConfigurationFile) {
		this.repositoryConfigurationFile = repositoryConfigurationFile;
	}

	@Override
	public String getLabel() {
		return CLIENT_LABEL;
	}

	@Override
	public AbstractTaskAttachmentHandler getTaskAttachmentHandler() {
		return attachmentHandler;
	}

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

	@Override
	public void updateTaskFromTaskData(TaskRepository repository, ITask task, TaskData taskData) {
		TaskMapper scheme = getTaskMapping(taskData);
		scheme.applyTo(task);

		task.setUrl(BugzillaClient.getBugUrlWithoutLogin(repository.getRepositoryUrl(), taskData.getTaskId()));

		boolean isComplete = false;
		TaskAttribute attributeStatus = taskData.getRoot().getMappedAttribute(TaskAttribute.STATUS);
		if (attributeStatus != null) {
			RepositoryConfiguration configuration = getRepositoryConfiguration(repository.getRepositoryUrl());
			if (configuration == null || configuration.getClosedStatusValues().isEmpty()) {
				isComplete = attributeStatus.getValue().equals(IBugzillaConstants.VALUE_STATUS_RESOLVED)
						|| attributeStatus.getValue().equals(IBugzillaConstants.VALUE_STATUS_CLOSED)
						|| attributeStatus.getValue().equals(IBugzillaConstants.VALUE_STATUS_VERIFIED);
			} else {
				isComplete = configuration.getClosedStatusValues().contains(attributeStatus.getValue());
			}
		}

		if (taskData.isPartial()) {
			if (isComplete) {
				if (task.getCompletionDate() == null) {
					task.setCompletionDate(new Date(0));
				}
			} else {
				if (task.getCompletionDate() != null) {
					task.setCompletionDate(null);
				}
			}
		} else {
			// Completion Date
			if (isComplete) {
				Date completionDate = null;

				List<TaskAttribute> taskComments = taskData.getAttributeMapper().getAttributesByType(taskData,
						TaskAttribute.TYPE_COMMENT);
				if (taskComments != null && taskComments.size() > 0) {
					TaskAttribute lastComment = taskComments.get(taskComments.size() - 1);
					if (lastComment != null) {
						TaskAttribute attributeCommentDate = lastComment.getMappedAttribute(TaskAttribute.COMMENT_DATE);
						if (attributeCommentDate != null) {
							try {
								completionDate = new SimpleDateFormat(COMMENT_FORMAT).parse(attributeCommentDate.getValue());
							} catch (ParseException e) {
								// ignore
							}
						}
					}
				}

				if (completionDate == null) {
					// Use last modified date
					TaskAttribute attributeLastModified = taskData.getRoot().getMappedAttribute(
							TaskAttribute.DATE_MODIFICATION);
					if (attributeLastModified != null && attributeLastModified.getValue().length() > 0) {
						completionDate = taskData.getAttributeMapper().getDateValue(attributeLastModified);
					}
				}

				if (completionDate == null) {
					completionDate = new Date();
				}

				task.setCompletionDate(completionDate);
			} else {
				task.setCompletionDate(null);
			}

			// Bugzilla Specific Attributes

			// Product
			if (scheme.getProduct() != null) {
				task.setAttribute(TaskAttribute.PRODUCT, scheme.getProduct());
			}

			// Severity
			TaskAttribute attrSeverity = taskData.getRoot().getMappedAttribute(BugzillaAttribute.BUG_SEVERITY.getKey());
			if (attrSeverity != null && !attrSeverity.getValue().equals("")) { //$NON-NLS-1$
				task.setAttribute(BugzillaAttribute.BUG_SEVERITY.getKey(), attrSeverity.getValue());
			}

		}

		updateExtendedAttributes(task, taskData);
	}

	private void updateExtendedAttributes(ITask task, TaskData taskData) {
		// Set meta bugzilla task attribute values
		for (BugzillaAttribute bugzillaReportElement : BugzillaAttribute.EXTENDED_ATTRIBUTES) {
			TaskAttribute taskAttribute = taskData.getRoot().getAttribute(bugzillaReportElement.getKey());
			if (taskAttribute != null) {
				task.setAttribute(bugzillaReportElement.getKey(), taskAttribute.getValue());
			}
		}
	}

	@Override
	public void preSynchronization(ISynchronizationSession session, IProgressMonitor monitor) throws CoreException {
		TaskRepository repository = session.getTaskRepository();
		if (session.getTasks().isEmpty()) {
			return;
		}

		monitor = Policy.monitorFor(monitor);
		try {
			monitor.beginTask(Messages.BugzillaRepositoryConnector_checking_for_changed_tasks, session.getTasks()
					.size());

			if (repository.getSynchronizationTimeStamp() == null) {
				for (ITask task : session.getTasks()) {
					session.markStale(task);
				}
				return;
			}

			String dateString = repository.getSynchronizationTimeStamp();
			if (dateString == null) {
				dateString = ""; //$NON-NLS-1$
			}

			String urlQueryBase = repository.getRepositoryUrl() + CHANGED_BUGS_CGI_QUERY
					+ URLEncoder.encode(dateString, repository.getCharacterEncoding()) + CHANGED_BUGS_CGI_ENDDATE;

			StringBuilder urlQueryString = new StringBuilder(Math.min(30 + 9 * session.getTasks().size(), 7009));
			urlQueryString.append(urlQueryBase + BUG_ID);

			Set<ITask> changedTasks = new HashSet<ITask>();
			Iterator<ITask> itr = session.getTasks().iterator();
			int queryCounter = 0;
			Set<ITask> checking = new HashSet<ITask>();
			while (itr.hasNext()) {
				ITask task = itr.next();
				checking.add(task);
				queryCounter++;
				urlQueryString.append(URLEncoder.encode(task.getTaskId() + ",", repository.getCharacterEncoding())); //$NON-NLS-1$
				if (urlQueryString.length() >= 7000) {
					queryForChanged(repository, changedTasks, urlQueryString.toString(), session,
							new SubProgressMonitor(monitor, queryCounter));

					queryCounter = 0;
					urlQueryString.setLength(0);
					urlQueryString.append(urlQueryBase + BUG_ID);
				}

				if (!itr.hasNext() && queryCounter != 0) {
					queryForChanged(repository, changedTasks, urlQueryString.toString(), session,
							new SubProgressMonitor(monitor, queryCounter));
				}
			}

			for (ITask task : session.getTasks()) {
				if (changedTasks.contains(task)) {
					session.markStale(task);
				}
			}

		} catch (UnsupportedEncodingException e) {
			throw new CoreException(new Status(IStatus.ERROR, BugzillaCorePlugin.ID_PLUGIN,
					"Repository configured with unsupported encoding: " + repository.getCharacterEncoding() //$NON-NLS-1$
							+ "\n\n Unable to determine changed tasks.", e)); //$NON-NLS-1$
		} finally {
			monitor.done();
		}
	}

	private void queryForChanged(final TaskRepository repository, Set<ITask> changedTasks, String urlQueryString,
			ISynchronizationSession syncSession, IProgressMonitor monitor) throws UnsupportedEncodingException,
			CoreException {

		HashMap<String, ITask> taskById = new HashMap<String, ITask>();
		for (ITask task : syncSession.getTasks()) {
			taskById.put(task.getTaskId(), task);
		}

		BugzillaTaskDataCollector collector = new BugzillaTaskDataCollector();

		// TODO: Decouple from internals
		IRepositoryQuery query = new RepositoryQuery(repository.getConnectorKind(), ""); //$NON-NLS-1$
		query.setSummary(Messages.BugzillaRepositoryConnector_Query_for_changed_tasks);
		query.setUrl(urlQueryString);
		performQuery(repository, query, collector, syncSession, monitor);
		for (TaskData data : collector.getTaskData()) {
			ITask changedTask = taskById.get(data.getTaskId());
			if (changedTask != null) {
				changedTasks.add(changedTask);
			}
		}
		if (syncSession.getData() == null && collector.getQueryTimestamp() != null) {
			syncSession.setData(collector.getQueryTimestamp());
		}

	}

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

	@Override
	public boolean canCreateNewTask(TaskRepository repository) {
		return true;
	}

	@Override
	public IStatus performQuery(TaskRepository repository, final IRepositoryQuery query,
			TaskDataCollector resultCollector, ISynchronizationSession event, IProgressMonitor monitor) {

		monitor = Policy.monitorFor(monitor);
		try {
			monitor.beginTask(Messages.BugzillaRepositoryConnector_running_query, IProgressMonitor.UNKNOWN);
			BugzillaClient client = getClientManager().getClient(repository, new SubProgressMonitor(monitor, 1));
			TaskAttributeMapper mapper = getTaskDataHandler().getAttributeMapper(repository);
			boolean hitsReceived = client.getSearchHits(query, resultCollector, mapper, monitor);
			if (!hitsReceived) {
				// XXX: HACK in case of ip change bugzilla can return 0 hits
				// due to invalid authorization token, forcing relogin fixes
				client.logout(monitor);
				client.getSearchHits(query, resultCollector, mapper, monitor);
			}

			if (resultCollector instanceof BugzillaTaskDataCollector) {
				BugzillaTaskDataCollector bCollector = (BugzillaTaskDataCollector) resultCollector;
				if (bCollector.getQueryTimestamp() != null) {
					Date queryDate = ((BugzillaAttributeMapper) mapper).getDate(BugzillaAttribute.DELTA_TS.getKey(),
							bCollector.getQueryTimestamp());
					if (queryDate != null) {
						// Ensure time is in right format
						event.setData(new SimpleDateFormat(TIMESTAMP_WITH_OFFSET).format(queryDate));
					}
				}
			}

			return Status.OK_STATUS;
		} catch (UnrecognizedReponseException e) {
			return new Status(IStatus.ERROR, BugzillaCorePlugin.ID_PLUGIN, IStatus.INFO,
					Messages.BugzillaRepositoryConnector_Unrecognized_response_from_server, e);
		} catch (IOException e) {
			return new Status(IStatus.ERROR, BugzillaCorePlugin.ID_PLUGIN, IStatus.ERROR, MessageFormat.format(
					Messages.BugzillaRepositoryConnector_Check_repository_configuration, e.getMessage()), e);
		} catch (CoreException e) {
			return e.getStatus();
		} finally {
			monitor.done();
		}
	}

	@Override
	public String getRepositoryUrlFromTaskUrl(String url) {
		if (url == null) {
			return null;
		}
		int index = url.indexOf(IBugzillaConstants.URL_GET_SHOW_BUG);
		return index == -1 ? null : url.substring(0, index);
	}

	@Override
	public String getTaskIdFromTaskUrl(String url) {
		if (url == null) {
			return null;
		}
		int anchorIndex = url.lastIndexOf("#"); //$NON-NLS-1$
		String bugUrl = url;
		if (anchorIndex != -1) {
			bugUrl = url.substring(0, anchorIndex);
		}

		int index = bugUrl.indexOf(IBugzillaConstants.URL_GET_SHOW_BUG);
		return index == -1 ? null : bugUrl.substring(index + IBugzillaConstants.URL_GET_SHOW_BUG.length());
	}

	@Override
	public String getTaskUrl(String repositoryUrl, String taskId) {
		try {
			return BugzillaClient.getBugUrlWithoutLogin(repositoryUrl, taskId);
		} catch (Exception e) {
			StatusHandler.log(new Status(IStatus.ERROR, BugzillaCorePlugin.ID_PLUGIN,
					"Error constructing task url for " + repositoryUrl + "  id:" + taskId, e)); //$NON-NLS-1$ //$NON-NLS-2$
		}
		return null;
	}

	@Override
	public String getTaskIdPrefix() {
		return "bug"; //$NON-NLS-1$
	}

	public BugzillaClientManager getClientManager() {
		if (clientManager == null) {
			clientManager = new BugzillaClientManager(this);
		}
		return clientManager;
	}

	@Override
	public void updateRepositoryConfiguration(TaskRepository repository, IProgressMonitor monitor) throws CoreException {
		if (repository != null) {
			getRepositoryConfiguration(repository, true, monitor);
		}
	}

	@Override
	public boolean isRepositoryConfigurationStale(TaskRepository repository, IProgressMonitor monitor)
			throws CoreException {
		if (super.isRepositoryConfigurationStale(repository, monitor)) {
			boolean result = true;
			BugzillaClient client = getClientManager().getClient(repository, monitor);
			if (client != null) {
				String timestamp = client.getConfigurationTimestamp(monitor);
				if (timestamp != null) {
					String oldTimestamp = repository.getProperty(IBugzillaConstants.PROPERTY_CONFIGTIMESTAMP);
					if (oldTimestamp != null) {
						result = !timestamp.equals(oldTimestamp);
					}
					repository.setProperty(IBugzillaConstants.PROPERTY_CONFIGTIMESTAMP, timestamp);
				}
			}
			return result;
		}
		return false;
	}

	public static void addLanguageSetting(BugzillaLanguageSettings language) {
		if (!languages.contains(language)) {
			BugzillaRepositoryConnector.languages.add(language);
		}
	}

	public static Set<BugzillaLanguageSettings> getLanguageSettings() {
		return languages;
	}

	/** returns default language if language not found */
	public static BugzillaLanguageSettings getLanguageSetting(String label) {
		for (BugzillaLanguageSettings language : getLanguageSettings()) {
			if (language.getLanguageName().equals(label)) {
				return language;
			}
		}
		return enSetting;
	}

	@Override
	public void postSynchronization(ISynchronizationSession event, IProgressMonitor monitor) throws CoreException {
		try {
			monitor.beginTask("", 1); //$NON-NLS-1$
			if (event.isFullSynchronization() && event.getStatus() == null) {
				event.getTaskRepository().setSynchronizationTimeStamp(getSynchronizationTimestamp(event));
			}
		} finally {
			monitor.done();
		}
	}

	@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 boolean hasTaskChanged(TaskRepository taskRepository, ITask task, TaskData taskData) {
		if (taskData.isPartial() && task.getCreationDate() != null) {
			return false;
		}

		// Security token
		// Updated on the task upon each open (synch) to keep the most current token available for submission - bug#263318
		TaskAttribute attrSecurityToken = taskData.getRoot().getMappedAttribute(BugzillaAttribute.TOKEN.getKey());
		if (attrSecurityToken != null && !attrSecurityToken.getValue().equals("")) { //$NON-NLS-1$
			task.setAttribute(BugzillaAttribute.TOKEN.getKey(), attrSecurityToken.getValue());
		}

		String lastKnownMod = task.getAttribute(BugzillaAttribute.DELTA_TS.getKey());
		if (lastKnownMod != null) {

			TaskAttribute attrModification = taskData.getRoot().getMappedAttribute(TaskAttribute.DATE_MODIFICATION);
			if (attrModification != null && attrModification.getValue() != null
					&& attrModification.getValue().length() > 0) {

				boolean cachedHasTZ = hasTimzone(lastKnownMod);
				boolean repoHasTZ = hasTimzone(attrModification.getValue());
				if (!cachedHasTZ && !repoHasTZ) { // State 1
					return !lastKnownMod.equals(attrModification.getValue());
				}

				BugzillaAttributeMapper mapper = (BugzillaAttributeMapper) taskData.getAttributeMapper();
				Date oldModDate = mapper.getDate(BugzillaAttribute.DELTA_TS.getKey(), lastKnownMod);
				Date newModDate = mapper.getDateValue(attrModification);

				// If either of the dates can't be parsed, fall back to string comparison
				if (oldModDate == null) {
					((AbstractTask) task).setStatus(new Status(IStatus.ERROR, BugzillaCorePlugin.ID_PLUGIN,
							"Unable to parse cached task modification timestamp " + lastKnownMod)); //$NON-NLS-1$
					return !lastKnownMod.equals(attrModification.getValue());
				} else if (newModDate == null) {
					((AbstractTask) task).setStatus(new Status(IStatus.ERROR, BugzillaCorePlugin.ID_PLUGIN,
							"Unable to parse incoming task modification timestamp " + attrModification.getValue())); //$NON-NLS-1$
					return !lastKnownMod.equals(attrModification.getValue());
				}

				if ((cachedHasTZ && !repoHasTZ) || (!cachedHasTZ && repoHasTZ)) { // State 2 (unlikely) || Sate 3
					long delta = Math.abs(newModDate.getTime() - oldModDate.getTime());
					if (delta == 0) {
						return false;
					} else if (delta > 0 && delta % HOUR == 0 && delta < 24 * HOUR) {
						// If same time but in different time zones, ignore/migrate
						return false;
					}
					return true;
				} else if (cachedHasTZ && repoHasTZ) { //State 4 (of 4)
					// Date Compare
					return oldModDate.compareTo(newModDate) != 0;
				}
			}
		}
		return true;
	}

	private boolean hasTimzone(String dateString) {
		if (dateString == null || dateString.length() == 0) {
			return false;
		}
		String[] parts = dateString.split(" "); //$NON-NLS-1$
		boolean hasTimeZone = (parts != null && parts.length == 3);
		return hasTimeZone;
	}

	@Override
	public Collection<TaskRelation> getTaskRelations(TaskData taskData) {
		List<TaskRelation> relations = new ArrayList<TaskRelation>();
		TaskAttribute attribute = taskData.getRoot().getAttribute(BugzillaAttribute.DEPENDSON.getKey());
		if (attribute != null && attribute.getValue().length() > 0) {
			for (String taskId : attribute.getValue().split(",")) { //$NON-NLS-1$
				relations.add(TaskRelation.subtask(taskId.trim()));
			}
		}
		attribute = taskData.getRoot().getAttribute(BugzillaAttribute.BLOCKED.getKey());
		if (attribute != null && attribute.getValue().length() > 0) {
			for (String taskId : attribute.getValue().split(",")) { //$NON-NLS-1$
				relations.add(TaskRelation.parentTask(taskId.trim()));
			}
		}
		return relations;
	}

	private String getSynchronizationTimestamp(ISynchronizationSession event) {
		Date mostRecent = new Date(0);
		String mostRecentTimeStamp = event.getTaskRepository().getSynchronizationTimeStamp();
		if (event.getData() != null) {
			mostRecentTimeStamp = (String) event.getData();
		} else {
			for (ITask task : event.getChangedTasks()) {
				Date taskModifiedDate = task.getModificationDate();
				if (taskModifiedDate != null && taskModifiedDate.after(mostRecent)) {
					mostRecent = taskModifiedDate;
					mostRecentTimeStamp = task.getAttribute(BugzillaAttribute.DELTA_TS.getKey());
				}
			}
		}
		return mostRecentTimeStamp;
	}

	@Override
	public boolean hasRepositoryDueDate(TaskRepository taskRepository, ITask task, TaskData taskData) {
		return taskData.getRoot().getAttribute(BugzillaAttribute.ESTIMATED_TIME.getKey()) != null;
	}

	@Override
	public TaskMapper getTaskMapping(final TaskData taskData) {
		return new TaskMapper(taskData) {
			@Override
			public String getTaskKey() {
				TaskAttribute attribute = getTaskData().getRoot().getAttribute(BugzillaAttribute.BUG_ID.getKey());
				if (attribute != null) {
					return attribute.getValue();
				}
				return super.getTaskKey();
			}

			@Override
			public String getTaskKind() {
				return taskData.getConnectorKind();
			}

			@Override
			public String getTaskUrl() {
				return taskData.getRepositoryUrl();
			}

			@Override
			public PriorityLevel getPriorityLevel() {
				RepositoryConfiguration repositoryConfiguration = BugzillaRepositoryConnector.this.getRepositoryConfiguration(taskData.getRepositoryUrl());
				BugzillaVersion bugzillaVersion;
				if (repositoryConfiguration != null) {
					bugzillaVersion = repositoryConfiguration.getInstallVersion();
				} else {
					bugzillaVersion = BugzillaVersion.MIN_VERSION;
				}
				if (bugzillaVersion.compareTo(BugzillaVersion.BUGZILLA_3_6) >= 0) {
					BugzillaPriorityLevel bugzillaPriorityLevel = BugzillaPriorityLevel.fromPriority(getPriority());
					if (bugzillaPriorityLevel != null) {
						return bugzillaPriorityLevel.toPriorityLevel();
					}
				}
				return super.getPriorityLevel();
			}
		};
	}

	/** public for testing */
	public synchronized void readRepositoryConfigurationFile() {
		if (cacheFileRead || repositoryConfigurationFile == null || !repositoryConfigurationFile.exists()) {
			return;
		}

		synchronized (repositoryConfigurations) {
			ObjectInputStream in = null;
			try {
				in = new ObjectInputStream(new FileInputStream(repositoryConfigurationFile));
				int size = in.readInt();
				for (int nX = 0; nX < size; nX++) {
					RepositoryConfiguration item = (RepositoryConfiguration) in.readObject();
					if (item != null) {
						repositoryConfigurations.put(item.getRepositoryUrl(), item);
					}
				}
			} catch (Exception e) {
				StatusHandler.log(new Status(IStatus.INFO, BugzillaCorePlugin.ID_PLUGIN,
						ERROR_INCOMPATIBLE_CONFIGURATION));
				try {
					if (in != null) {
						in.close();
					}
					if (repositoryConfigurationFile != null && repositoryConfigurationFile.exists()) {
						if (repositoryConfigurationFile.delete()) {
							// successfully deleted
						} else {
							StatusHandler.log(new Status(IStatus.ERROR, BugzillaCorePlugin.ID_PLUGIN, 0,
									ERROR_DELETING_CONFIGURATION, e));
						}
					}

				} catch (Exception ex) {
					StatusHandler.log(new Status(IStatus.ERROR, BugzillaCorePlugin.ID_PLUGIN, 0,
							ERROR_DELETING_CONFIGURATION, e));
				}
			} finally {
				cacheFileRead = true;
				if (in != null) {
					try {
						in.close();
					} catch (IOException e) {
						// ignore
					}
				}
			}
		}
	}

	/**
	 * Retrieves the latest repository configuration from the server
	 */
	public RepositoryConfiguration getRepositoryConfiguration(TaskRepository repository, boolean forceRefresh,
			IProgressMonitor monitor) throws CoreException {
		monitor = Policy.monitorFor(monitor);
		try {
			readRepositoryConfigurationFile();
			RepositoryConfiguration configuration;
			configuration = repositoryConfigurations.get(repository.getRepositoryUrl());
			if (configuration == null || forceRefresh) {
				synchronized (repositoryConfigurations) {
					// check if another thread already retrieved configuration
					configuration = repositoryConfigurations.get(repository.getRepositoryUrl());
					if (configuration == null || forceRefresh) {
						String eTag = null;
						Date lastModifiedHeader = null;
						if (configuration != null && !forceRefresh) {
							eTag = configuration.getETagValue();
							lastModifiedHeader = configuration.getLastModifiedHeader();
						}
						BugzillaClient client = getClientManager().getClient(repository, monitor);
						configuration = client.getRepositoryConfiguration(monitor, eTag);
						boolean newer = true;
						if (configuration != null) {
							if (lastModifiedHeader != null) {
								Date configLastModifiedHeader = configuration.getLastModifiedHeader();
								if (configLastModifiedHeader != null) {
									newer = !configLastModifiedHeader.before(lastModifiedHeader);
								}
							}
							if (newer) {
								String configVersion = configuration.getInstallVersion().toString();
								String repositoryVersion = repository.getVersion();
								if (!configVersion.equals(repositoryVersion)) {
									repository.setVersion(configVersion);
								}
								internalAddConfiguration(configuration);
							}
						}
					}
				}
			}
			return configuration;
		} catch (IOException e) {
			throw new CoreException(new Status(IStatus.ERROR, BugzillaCorePlugin.ID_PLUGIN, 1,
					"Error retrieving task attributes from repository.\n\n" + e.getMessage(), e)); //$NON-NLS-1$
		} catch (CoreException e) {
			if (e.getMessage().equals("Not changed")) { //$NON-NLS-1$
				RepositoryConfiguration configuration = repositoryConfigurations.get(repository.getRepositoryUrl());
				if (configuration == null) {
					throw new CoreException(new BugzillaStatus(IStatus.ERROR, BugzillaCorePlugin.ID_PLUGIN,
							RepositoryStatus.ERROR_INTERNAL, "Failed to retrieve repository configuration for " //$NON-NLS-1$
									+ repository.getRepositoryUrl().toString()));

				}
				return configuration;
			} else {
				throw e;
			}
		}
	}

	public void addRepositoryConfiguration(RepositoryConfiguration config) {
		if (config != null) {
			readRepositoryConfigurationFile();
			synchronized (repositoryConfigurations) {
				internalAddConfiguration(config);
			}
		}
	}

	private void internalAddConfiguration(RepositoryConfiguration config) {
		repositoryConfigurations.remove(config.getRepositoryUrl());
		repositoryConfigurations.put(config.getRepositoryUrl(), config);
	}

	public RepositoryConfiguration getRepositoryConfiguration(String repositoryUrl) {
		readRepositoryConfigurationFile();
		return repositoryConfigurations.get(repositoryUrl);
	}

	/** public for testing */
	public void removeConfiguration(RepositoryConfiguration config) {
		synchronized (repositoryConfigurations) {
			repositoryConfigurations.remove(config.getRepositoryUrl());
		}
	}

	/** public for testing */
	public void writeRepositoryConfigFile() {
		if (repositoryConfigurationFile != null) {
			ObjectOutputStream out = null;
			try {
				Set<RepositoryConfiguration> tempConfigs;
				synchronized (repositoryConfigurations) {
					tempConfigs = new HashSet<RepositoryConfiguration>(repositoryConfigurations.values());
				}
				if (tempConfigs.size() > 0) {
					out = new ObjectOutputStream(new FileOutputStream(repositoryConfigurationFile));
					out.writeInt(tempConfigs.size());
					for (RepositoryConfiguration repositoryConfiguration : tempConfigs) {
						if (repositoryConfiguration != null) {
							out.writeObject(repositoryConfiguration);
						}
					}
				}
			} catch (IOException e) {
				StatusHandler.log(new Status(IStatus.WARNING, BugzillaCorePlugin.ID_PLUGIN, 0,
						"Failed to write repository configuration cache", e)); //$NON-NLS-1$
			} finally {
				if (out != null) {
					try {
						out.close();
					} catch (IOException e) {
						// ignore
					}
				}
			}
		}
	}

	public void stop() {
		writeRepositoryConfigFile();
	}

	public void setPlatformDefaultsOrGuess(TaskRepository repository, TaskData newBugModel) {

		String platform = repository.getProperty(IBugzillaConstants.BUGZILLA_DEF_PLATFORM);
		String os = repository.getProperty(IBugzillaConstants.BUGZILLA_DEF_OS);

		// set both or none
		if (null != os && null != platform) {
			TaskAttribute opSysAttribute = newBugModel.getRoot().getAttribute(BugzillaAttribute.OP_SYS.getKey());
			TaskAttribute platformAttribute = newBugModel.getRoot().getAttribute(
					BugzillaAttribute.REP_PLATFORM.getKey());

			// TODO something can still go wrong when the allowed values on the repository change...
			opSysAttribute.setValue(os);
			platformAttribute.setValue(platform);
			return;
		}
		// fall through to old code
		setPlatformOptions(newBugModel);
	}

	public void setPlatformOptions(TaskData newBugModel) {
		try {

			// Get OS Lookup Map
			// Check that the result is in Values, if it is not, set it to other
			// Defaults to the first of each (sorted) list All, All
			TaskAttribute opSysAttribute = newBugModel.getRoot().getAttribute(BugzillaAttribute.OP_SYS.getKey());
			TaskAttribute platformAttribute = newBugModel.getRoot().getAttribute(
					BugzillaAttribute.REP_PLATFORM.getKey());

			String OS = Platform.getOS();
			String platform = Platform.getOSArch();
			String ws = Platform.getWS();

			String bugzillaOS = null; // Bugzilla String for OS
			String bugzillaPlatform = null; // Bugzilla String for Platform
			String[] wsExtentions = null;
/*
			AIX -> AIX
			Linux -> Linux
			HP-UX -> HP-UX
			Solaris -> Solaris
			MacOS X -> Mac OS X
 */

			if (ws.length() > 1) {
				char first = ws.charAt(0);
				char firstLower = Character.toLowerCase(first);
				char firstUpper = Character.toUpperCase(first);
				String[] wsExtentionsTemp = { " - " + firstUpper + ws.substring(1, ws.length()), //$NON-NLS-1$
						" - " + firstLower + ws.substring(1, ws.length()), //$NON-NLS-1$
						" " + firstUpper + ws.substring(1, ws.length()), //$NON-NLS-1$
						" " + firstLower + ws.substring(1, ws.length()), "" }; //$NON-NLS-1$//$NON-NLS-2$
				wsExtentions = wsExtentionsTemp;
			} else if (ws.length() == 1) {
				char first = ws.charAt(0);
				char firstLower = Character.toLowerCase(first);
				char firstUpper = Character.toUpperCase(first);
				String[] wsExtentionsTemp = { " - " + firstUpper, " - " + firstLower, " " + firstUpper, //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
						" " + firstLower, "" }; //$NON-NLS-1$//$NON-NLS-2$
				wsExtentions = wsExtentionsTemp;
			} else {
				String[] wsExtentionsTemp = { "" }; //$NON-NLS-1$
				wsExtentions = wsExtentionsTemp;
			}

			bugzillaOS = System.getProperty("os.name") + " " + System.getProperty("os.version"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			// We start with the most specific Value as the Search String.
			// If we didn't find it we remove the last part of the version String or the OS Name from
			// the Search String and continue with the test until we found it or the Search String is empty.
			//
			// The search in casesensitive.
			if (opSysAttribute != null) {
				for (String element : wsExtentions) {
					String bugzillaOSTemp = bugzillaOS;
					while (bugzillaOSTemp != null && opSysAttribute.getOption(bugzillaOSTemp + element) == null) {
						int dotindex = bugzillaOSTemp.lastIndexOf('.');
						if (dotindex > 0) {
							bugzillaOSTemp = bugzillaOSTemp.substring(0, dotindex);
						} else {
							int spaceindex = bugzillaOSTemp.lastIndexOf(' ');
							if (spaceindex > 0) {
								bugzillaOSTemp = bugzillaOSTemp.substring(0, spaceindex);
							} else {
								bugzillaOSTemp = null;
							}
						}
					}
					if (bugzillaOSTemp != null) {
						bugzillaOS = bugzillaOSTemp + element;
						break;
					}
				}
			} else {
				bugzillaOS = null;
			}

			if (platform != null && java2buzillaPlatformMap.containsKey(platform)) {
				bugzillaPlatform = java2buzillaPlatformMap.get(platform);
				// Bugzilla knows the following Platforms [All, Macintosh, Other, PC, Power PC, Sun]
				// Platform.getOSArch() returns "x86" on Intel Mac's and "ppc" on Power Mac's
				// so bugzillaPlatform is "Power" or "PC".
				//
				// If the OS is "macosx" we change the Platform to "Macintosh"
				//
				if (bugzillaPlatform != null
						&& (bugzillaPlatform.compareTo("Power") == 0 || bugzillaPlatform.compareTo("PC") == 0) //$NON-NLS-1$ //$NON-NLS-2$
						&& OS != null && OS.compareTo("macosx") == 0) { //$NON-NLS-1$
					// TODO: this may not even be a legal value in another repository!
					bugzillaPlatform = "Macintosh"; //$NON-NLS-1$
				} else if (platformAttribute != null && platformAttribute.getOption(bugzillaPlatform) == null) {
					// If the platform we found is not int the list of available
					// optinos, set the
					// Bugzilla Platform to null, and juse use "other"
					bugzillaPlatform = null;
				}
			}
			// Set the OS and the Platform in the taskData
			if (bugzillaOS != null && opSysAttribute != null && opSysAttribute.getOption(bugzillaOS) != null) {
				opSysAttribute.setValue(bugzillaOS);
			}

			/*else if (opSysAttribute != null && opSysAttribute.getOption(OPTION_ALL) != null) {
				opSysAttribute.setValue(OPTION_ALL);
			}*/

			if (bugzillaPlatform != null && platformAttribute != null
					&& platformAttribute.getOption(bugzillaPlatform) != null) {
				platformAttribute.setValue(bugzillaPlatform);
			}
			/*else if (opSysAttribute != null && platformAttribute != null
					&& platformAttribute.getOption(OPTION_ALL) != null) {
				opSysAttribute.setValue(OPTION_ALL);
			}*/

		} catch (Exception e) {
			StatusHandler.log(new Status(IStatus.ERROR, BugzillaCorePlugin.ID_PLUGIN, "could not set platform options", //$NON-NLS-1$
					e));
		}
	}

	public enum BugzillaPriorityLevel {
		HIGHEST, HIGH, NORMAL, LOW, LOWEST, NONE;

		public static BugzillaPriorityLevel fromPriority(String priority) {
			if (priority == null) {
				return null;
			}
			if (priority.equals("Highest")) { //$NON-NLS-1$
				return HIGHEST;
			}
			if (priority.equals("High")) { //$NON-NLS-1$
				return HIGH;
			}
			if (priority.equals("Normal")) { //$NON-NLS-1$
				return NORMAL;
			}
			if (priority.equals("Low")) { //$NON-NLS-1$
				return LOW;
			}
			if (priority.equals("Lowest")) { //$NON-NLS-1$
				return LOWEST;
			}
			if (priority.equals("Lowest")) { //$NON-NLS-1$
				return LOWEST;
			}
			if (priority.equals("---")) { //$NON-NLS-1$
				return NONE;
			}
			return null;
		}

		public PriorityLevel toPriorityLevel() {
			switch (this) {
			case HIGHEST:
				return PriorityLevel.P1;
			case HIGH:
				return PriorityLevel.P2;
			case NORMAL:
				return PriorityLevel.P3;
			case LOW:
				return PriorityLevel.P4;
			case LOWEST:
				return PriorityLevel.P5;
			case NONE:
				return PriorityLevel.P3;
			default:
				return null;
			}
		}

		@Override
		public String toString() {
			switch (this) {
			case HIGHEST:
				return "Highest"; //$NON-NLS-1$
			case HIGH:
				return "High"; //$NON-NLS-1$
			case NORMAL:
				return "Normal"; //$NON-NLS-1$
			case LOW:
				return "Low"; //$NON-NLS-1$
			case LOWEST:
				return "Lowest"; //$NON-NLS-1$
			case NONE:
				return "---"; //$NON-NLS-1$
			default:
				return null;
			}
		}
	}

	@Override
	public boolean canGetTaskHistory(TaskRepository repository, ITask task) {
		return Boolean.parseBoolean(repository.getProperty(IBugzillaConstants.BUGZILLA_USE_XMLRPC));
	}

	@Override
	public TaskHistory getTaskHistory(TaskRepository repository, ITask task, IProgressMonitor monitor)
			throws CoreException {
		BugzillaClient client = getClientManager().getClient(repository, monitor);
		BugHistory bugHistory = client.getBugHistory(task.getTaskId(), monitor).get(0);
		TaskHistory history = new TaskHistory(repository, task);
		for (BugHistory.Revision bugRevision : bugHistory.getRevisions()) {
			TaskRevision revision = new TaskRevision(Long.toString(bugRevision.getWhen().getTime()),
					bugRevision.getWhen(), repository.createPerson(bugRevision.getWho()));
			history.add(revision);
			for (BugHistory.Change bugChange : bugRevision.getChanges()) {
				String attributeId;
				if (bugChange.getAttachmentId() > 0) {
					attributeId = TaskAttribute.PREFIX_ATTACHMENT + bugChange.getAttachmentId();
				} else {
					attributeId = bugChange.getFieldName();
				}
				TaskRevision.Change change = new TaskRevision.Change(attributeId, bugChange.getFieldName(),
						bugChange.getRemoved(), bugChange.getAdded());
				revision.add(change);
			}
		}
		return history;
	}
}
