/*
 * Copyright 2013 gitblit.com.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.gitblit.tickets;

import java.io.IOException;
import java.text.MessageFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.extensions.TicketHook;
import com.gitblit.manager.IManager;
import com.gitblit.manager.INotificationManager;
import com.gitblit.manager.IPluginManager;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.manager.IUserManager;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.TicketModel;
import com.gitblit.models.TicketModel.Attachment;
import com.gitblit.models.TicketModel.Change;
import com.gitblit.models.TicketModel.Field;
import com.gitblit.models.TicketModel.Patchset;
import com.gitblit.models.TicketModel.PatchsetType;
import com.gitblit.models.TicketModel.Status;
import com.gitblit.models.TicketModel.TicketLink;
import com.gitblit.tickets.TicketIndexer.Lucene;
import com.gitblit.utils.DeepCopier;
import com.gitblit.utils.DiffUtils;
import com.gitblit.utils.JGitUtils;
import com.gitblit.utils.DiffUtils.DiffStat;
import com.gitblit.utils.StringUtils;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;

/**
 * Abstract parent class of a ticket service that stubs out required methods
 * and transparently handles Lucene indexing.
 *
 * @author James Moger
 *
 */
public abstract class ITicketService implements IManager {

	public static final String SETTING_UPDATE_DIFFSTATS = "migration.updateDiffstats";

	private static final String LABEL = "label";

	private static final String MILESTONE = "milestone";

	private static final String STATUS = "status";

	private static final String COLOR = "color";

	private static final String DUE = "due";

	private static final String DUE_DATE_PATTERN = "yyyy-MM-dd";

	/**
	 * Object filter interface to querying against all available ticket models.
	 */
	public interface TicketFilter {

		boolean accept(TicketModel ticket);
	}

	protected final Logger log;

	protected final IStoredSettings settings;

	protected final IRuntimeManager runtimeManager;

	protected final INotificationManager notificationManager;

	protected final IUserManager userManager;

	protected final IRepositoryManager repositoryManager;

	protected final IPluginManager pluginManager;

	protected final TicketIndexer indexer;

	private final Cache<TicketKey, TicketModel> ticketsCache;

	private final Map<String, List<TicketLabel>> labelsCache;

	private final Map<String, List<TicketMilestone>> milestonesCache;

	private final boolean updateDiffstats;

	private static class TicketKey {
		final String repository;
		final long ticketId;

		TicketKey(RepositoryModel repository, long ticketId) {
			this.repository = repository.name;
			this.ticketId = ticketId;
		}

		@Override
		public int hashCode() {
			return (repository + ticketId).hashCode();
		}

		@Override
		public boolean equals(Object o) {
			if (o instanceof TicketKey) {
				return o.hashCode() == hashCode();
			}
			return false;
		}

		@Override
		public String toString() {
			return repository + ":" + ticketId;
		}
	}


	/**
	 * Creates a ticket service.
	 */
	public ITicketService(
			IRuntimeManager runtimeManager,
			IPluginManager pluginManager,
			INotificationManager notificationManager,
			IUserManager userManager,
			IRepositoryManager repositoryManager) {

		this.log = LoggerFactory.getLogger(getClass());
		this.settings = runtimeManager.getSettings();
		this.runtimeManager = runtimeManager;
		this.pluginManager = pluginManager;
		this.notificationManager = notificationManager;
		this.userManager = userManager;
		this.repositoryManager = repositoryManager;

		this.indexer = new TicketIndexer(runtimeManager);

		CacheBuilder<Object, Object> cb = CacheBuilder.newBuilder();
		this.ticketsCache = cb
				.maximumSize(1000)
				.expireAfterAccess(30, TimeUnit.MINUTES)
				.build();

		this.labelsCache = new ConcurrentHashMap<String, List<TicketLabel>>();
		this.milestonesCache = new ConcurrentHashMap<String, List<TicketMilestone>>();

		this.updateDiffstats = settings.getBoolean(SETTING_UPDATE_DIFFSTATS, true);
	}

	/**
	 * Start the service.
	 * @since 1.4.0
	 */
	@Override
	public final ITicketService start() {
		onStart();
		if (shouldReindex()) {
			log.info("Re-indexing all tickets...");
//			long startTime = System.currentTimeMillis();
			reindex();
//			float duration = (System.currentTimeMillis() - startTime) / 1000f;
//			log.info("Built Lucene index over all tickets in {} secs", duration);
		}
		return this;
	}

	/**
	 * Start the specific ticket service implementation.
	 *
	 * @since 1.9.0
	 */
	public abstract void onStart();

	/**
	 * Stop the service.
	 * @since 1.4.0
	 */
	@Override
	public final ITicketService stop() {
		indexer.close();
		ticketsCache.invalidateAll();
		repositoryManager.closeAll();
		close();
		return this;
	}

	/**
	 * Closes any open resources used by this service.
	 * @since 1.4.0
	 */
	protected abstract void close();

	/**
	 * Creates a ticket notifier.  The ticket notifier is not thread-safe!
	 * @since 1.4.0
	 */
	public TicketNotifier createNotifier() {
		return new TicketNotifier(
				runtimeManager,
				notificationManager,
				userManager,
				repositoryManager,
				this);
	}

	/**
	 * Returns the ready status of the ticket service.
	 *
	 * @return true if the ticket service is ready
	 * @since 1.4.0
	 */
	public boolean isReady() {
		return true;
	}

	/**
	 * Returns true if the new patchsets can be accepted for this repository.
	 *
	 * @param repository
	 * @return true if patchsets are being accepted
	 * @since 1.4.0
	 */
	public boolean isAcceptingNewPatchsets(RepositoryModel repository) {
		return isReady()
				&& settings.getBoolean(Keys.tickets.acceptNewPatchsets, true)
				&& repository.acceptNewPatchsets
				&& isAcceptingTicketUpdates(repository);
	}

	/**
	 * Returns true if new tickets can be manually created for this repository.
	 * This is separate from accepting patchsets.
	 *
	 * @param repository
	 * @return true if tickets are being accepted
	 * @since 1.4.0
	 */
	public boolean isAcceptingNewTickets(RepositoryModel repository) {
		return isReady()
				&& settings.getBoolean(Keys.tickets.acceptNewTickets, true)
				&& repository.acceptNewTickets
				&& isAcceptingTicketUpdates(repository);
	}

	/**
	 * Returns true if ticket updates are allowed for this repository.
	 *
	 * @param repository
	 * @return true if tickets are allowed to be updated
	 * @since 1.4.0
	 */
	public boolean isAcceptingTicketUpdates(RepositoryModel repository) {
		return isReady()
				&& repository.hasCommits
				&& repository.isBare
				&& !repository.isFrozen
				&& !repository.isMirror;
	}

	/**
	 * Returns true if the repository has any tickets
	 * @param repository
	 * @return true if the repository has tickets
	 * @since 1.4.0
	 */
	public boolean hasTickets(RepositoryModel repository) {
		return indexer.hasTickets(repository);
	}

	/**
	 * Reset all caches in the service.
	 * @since 1.4.0
	 */
	public final synchronized void resetCaches() {
		ticketsCache.invalidateAll();
		labelsCache.clear();
		milestonesCache.clear();
		resetCachesImpl();
	}

	/**
	 * Reset all caches in the service.
	 * @since 1.4.0
	 */
	protected abstract void resetCachesImpl();

	/**
	 * Reset any caches for the repository in the service.
	 * @since 1.4.0
	 */
	public final synchronized void resetCaches(RepositoryModel repository) {
		List<TicketKey> repoKeys = new ArrayList<TicketKey>();
		for (TicketKey key : ticketsCache.asMap().keySet()) {
			if (key.repository.equals(repository.name)) {
				repoKeys.add(key);
			}
		}
		ticketsCache.invalidateAll(repoKeys);
		labelsCache.remove(repository.name);
		milestonesCache.remove(repository.name);
		resetCachesImpl(repository);
	}

	/**
	 * Reset the caches for the specified repository.
	 *
	 * @param repository
	 * @since 1.4.0
	 */
	protected abstract void resetCachesImpl(RepositoryModel repository);


	/**
	 * Returns the list of labels for the repository.
	 *
	 * @param repository
	 * @return the list of labels
	 * @since 1.4.0
	 */
	public List<TicketLabel> getLabels(RepositoryModel repository) {
		String key = repository.name;
		if (labelsCache.containsKey(key)) {
			return labelsCache.get(key);
		}
		List<TicketLabel> list = new ArrayList<TicketLabel>();
		Repository db = repositoryManager.getRepository(repository.name);
		try {
			StoredConfig config = db.getConfig();
			Set<String> names = config.getSubsections(LABEL);
			for (String name : names) {
				TicketLabel label = new TicketLabel(name);
				label.color = config.getString(LABEL, name, COLOR);
				list.add(label);
			}
			labelsCache.put(key,  Collections.unmodifiableList(list));
		} catch (Exception e) {
			log.error("invalid tickets settings for " + repository, e);
		} finally {
			db.close();
		}
		return list;
	}

	/**
	 * Returns a TicketLabel object for a given label.  If the label is not
	 * found, a ticket label object is created.
	 *
	 * @param repository
	 * @param label
	 * @return a TicketLabel
	 * @since 1.4.0
	 */
	public TicketLabel getLabel(RepositoryModel repository, String label) {
		for (TicketLabel tl : getLabels(repository)) {
			if (tl.name.equalsIgnoreCase(label)) {
				String q = QueryBuilder.q(Lucene.rid.matches(repository.getRID())).and(Lucene.labels.matches(label)).build();
				tl.tickets = indexer.queryFor(q, 1, 0, Lucene.number.name(), true);
				return tl;
			}
		}
		return new TicketLabel(label);
	}

	/**
	 * Creates a label.
	 *
	 * @param repository
	 * @param milestone
	 * @param createdBy
	 * @return the label
	 * @since 1.4.0
	 */
	public synchronized TicketLabel createLabel(RepositoryModel repository, String label, String createdBy) {
		TicketLabel lb = new TicketMilestone(label);
		Repository db = null;
		try {
			db = repositoryManager.getRepository(repository.name);
			StoredConfig config = db.getConfig();
			config.setString(LABEL, label, COLOR, lb.color);
			config.save();
		} catch (IOException e) {
			log.error("failed to create label " + label + " in " + repository, e);
		} finally {
			if (db != null) {
				db.close();
			}
		}
		return lb;
	}

	/**
	 * Updates a label.
	 *
	 * @param repository
	 * @param label
	 * @param createdBy
	 * @return true if the update was successful
	 * @since 1.4.0
	 */
	public synchronized boolean updateLabel(RepositoryModel repository, TicketLabel label, String createdBy) {
		Repository db = null;
		try {
			db = repositoryManager.getRepository(repository.name);
			StoredConfig config = db.getConfig();
			config.setString(LABEL, label.name, COLOR, label.color);
			config.save();

			return true;
		} catch (IOException e) {
			log.error("failed to update label " + label + " in " + repository, e);
		} finally {
			if (db != null) {
				db.close();
			}
		}
		return false;
	}

	/**
	 * Renames a label.
	 *
	 * @param repository
	 * @param oldName
	 * @param newName
	 * @param createdBy
	 * @return true if the rename was successful
	 * @since 1.4.0
	 */
	public synchronized boolean renameLabel(RepositoryModel repository, String oldName, String newName, String createdBy) {
		if (StringUtils.isEmpty(newName)) {
			throw new IllegalArgumentException("new label can not be empty!");
		}
		Repository db = null;
		try {
			db = repositoryManager.getRepository(repository.name);
			TicketLabel label = getLabel(repository, oldName);
			StoredConfig config = db.getConfig();
			config.unsetSection(LABEL, oldName);
			config.setString(LABEL, newName, COLOR, label.color);
			config.save();

			for (QueryResult qr : label.tickets) {
				Change change = new Change(createdBy);
				change.unlabel(oldName);
				change.label(newName);
				updateTicket(repository, qr.number, change);
			}

			return true;
		} catch (IOException e) {
			log.error("failed to rename label " + oldName + " in " + repository, e);
		} finally {
			if (db != null) {
				db.close();
			}
		}
		return false;
	}

	/**
	 * Deletes a label.
	 *
	 * @param repository
	 * @param label
	 * @param createdBy
	 * @return true if the delete was successful
	 * @since 1.4.0
	 */
	public synchronized boolean deleteLabel(RepositoryModel repository, String label, String createdBy) {
		if (StringUtils.isEmpty(label)) {
			throw new IllegalArgumentException("label can not be empty!");
		}
		Repository db = null;
		try {
			db = repositoryManager.getRepository(repository.name);
			StoredConfig config = db.getConfig();
			config.unsetSection(LABEL, label);
			config.save();

			return true;
		} catch (IOException e) {
			log.error("failed to delete label " + label + " in " + repository, e);
		} finally {
			if (db != null) {
				db.close();
			}
		}
		return false;
	}

	/**
	 * Returns the list of milestones for the repository.
	 *
	 * @param repository
	 * @return the list of milestones
	 * @since 1.4.0
	 */
	public List<TicketMilestone> getMilestones(RepositoryModel repository) {
		String key = repository.name;
		if (milestonesCache.containsKey(key)) {
			return milestonesCache.get(key);
		}
		List<TicketMilestone> list = new ArrayList<TicketMilestone>();
		Repository db = repositoryManager.getRepository(repository.name);
		try {
			StoredConfig config = db.getConfig();
			Set<String> names = config.getSubsections(MILESTONE);
			for (String name : names) {
				TicketMilestone milestone = new TicketMilestone(name);
				milestone.status = Status.fromObject(config.getString(MILESTONE, name, STATUS), milestone.status);
				milestone.color = config.getString(MILESTONE, name, COLOR);
				String due = config.getString(MILESTONE, name, DUE);
				if (!StringUtils.isEmpty(due)) {
					try {
						milestone.due = new SimpleDateFormat(DUE_DATE_PATTERN).parse(due);
					} catch (ParseException e) {
						log.error("failed to parse {} milestone {} due date \"{}\"",
								new Object [] { repository, name, due });
					}
				}
				list.add(milestone);
			}
			milestonesCache.put(key, Collections.unmodifiableList(list));
		} catch (Exception e) {
			log.error("invalid tickets settings for " + repository, e);
		} finally {
			db.close();
		}
		return list;
	}

	/**
	 * Returns the list of milestones for the repository that match the status.
	 *
	 * @param repository
	 * @param status
	 * @return the list of milestones
	 * @since 1.4.0
	 */
	public List<TicketMilestone> getMilestones(RepositoryModel repository, Status status) {
		List<TicketMilestone> matches = new ArrayList<TicketMilestone>();
		for (TicketMilestone milestone : getMilestones(repository)) {
			if (status == milestone.status) {
				matches.add(milestone);
			}
		}
		return matches;
	}

	/**
	 * Returns the specified milestone or null if the milestone does not exist.
	 *
	 * @param repository
	 * @param milestone
	 * @return the milestone or null if it does not exist
	 * @since 1.4.0
	 */
	public TicketMilestone getMilestone(RepositoryModel repository, String milestone) {
		for (TicketMilestone ms : getMilestones(repository)) {
			if (ms.name.equalsIgnoreCase(milestone)) {
				TicketMilestone tm = DeepCopier.copy(ms);
				String q = QueryBuilder.q(Lucene.rid.matches(repository.getRID())).and(Lucene.milestone.matches(milestone)).build();
				tm.tickets = indexer.queryFor(q, 1, 0, Lucene.number.name(), true);
				return tm;
			}
		}
		return null;
	}

	/**
	 * Creates a milestone.
	 *
	 * @param repository
	 * @param milestone
	 * @param createdBy
	 * @return the milestone
	 * @since 1.4.0
	 */
	public synchronized TicketMilestone createMilestone(RepositoryModel repository, String milestone, String createdBy) {
		TicketMilestone ms = new TicketMilestone(milestone);
		Repository db = null;
		try {
			db = repositoryManager.getRepository(repository.name);
			StoredConfig config = db.getConfig();
			config.setString(MILESTONE, milestone, STATUS, ms.status.name());
			config.setString(MILESTONE, milestone, COLOR, ms.color);
			config.save();

			milestonesCache.remove(repository.name);
		} catch (IOException e) {
			log.error("failed to create milestone " + milestone + " in " + repository, e);
		} finally {
			if (db != null) {
				db.close();
			}
		}
		return ms;
	}

	/**
	 * Updates a milestone.
	 *
	 * @param repository
	 * @param milestone
	 * @param createdBy
	 * @return true if successful
	 * @since 1.4.0
	 */
	public synchronized boolean updateMilestone(RepositoryModel repository, TicketMilestone milestone, String createdBy) {
		Repository db = null;
		try {
			db = repositoryManager.getRepository(repository.name);
			StoredConfig config = db.getConfig();
			config.setString(MILESTONE, milestone.name, STATUS, milestone.status.name());
			config.setString(MILESTONE, milestone.name, COLOR, milestone.color);
			if (milestone.due != null) {
				config.setString(MILESTONE, milestone.name, DUE,
						new SimpleDateFormat(DUE_DATE_PATTERN).format(milestone.due));
			}
			config.save();

			milestonesCache.remove(repository.name);
			return true;
		} catch (IOException e) {
			log.error("failed to update milestone " + milestone + " in " + repository, e);
		} finally {
			if (db != null) {
				db.close();
			}
		}
		return false;
	}

	/**
	 * Renames a milestone.
	 *
	 * @param repository
	 * @param oldName
	 * @param newName
	 * @param createdBy
	 * @return true if successful
	 * @since 1.4.0
	 */
	public synchronized boolean renameMilestone(RepositoryModel repository, String oldName, String newName, String createdBy) {
		return renameMilestone(repository, oldName, newName, createdBy, true);
	}

	/**
	 * Renames a milestone.
	 *
	 * @param repository
	 * @param oldName
	 * @param newName
	 * @param createdBy
	 * @param notifyOpenTickets
	 * @return true if successful
	 * @since 1.6.0
	 */
	public synchronized boolean renameMilestone(RepositoryModel repository, String oldName,
			String newName, String createdBy, boolean notifyOpenTickets) {
		if (StringUtils.isEmpty(newName)) {
			throw new IllegalArgumentException("new milestone can not be empty!");
		}
		Repository db = null;
		try {
			db = repositoryManager.getRepository(repository.name);
			TicketMilestone tm = getMilestone(repository, oldName);
			if (tm == null) {
				return false;
			}
			StoredConfig config = db.getConfig();
			config.unsetSection(MILESTONE, oldName);
			config.setString(MILESTONE, newName, STATUS, tm.status.name());
			config.setString(MILESTONE, newName, COLOR, tm.color);
			if (tm.due != null) {
				config.setString(MILESTONE, newName, DUE,
						new SimpleDateFormat(DUE_DATE_PATTERN).format(tm.due));
			}
			config.save();

			milestonesCache.remove(repository.name);

			TicketNotifier notifier = createNotifier();
			for (QueryResult qr : tm.tickets) {
				Change change = new Change(createdBy);
				change.setField(Field.milestone, newName);
				TicketModel ticket = updateTicket(repository, qr.number, change);
				if (notifyOpenTickets && ticket.isOpen()) {
					notifier.queueMailing(ticket);
				}
			}
			if (notifyOpenTickets) {
				notifier.sendAll();
			}

			return true;
		} catch (IOException e) {
			log.error("failed to rename milestone " + oldName + " in " + repository, e);
		} finally {
			if (db != null) {
				db.close();
			}
		}
		return false;
	}

	/**
	 * Deletes a milestone.
	 *
	 * @param repository
	 * @param milestone
	 * @param createdBy
	 * @return true if successful
	 * @since 1.4.0
	 */
	public synchronized boolean deleteMilestone(RepositoryModel repository, String milestone, String createdBy) {
		return deleteMilestone(repository, milestone, createdBy, true);
	}

	/**
	 * Deletes a milestone.
	 *
	 * @param repository
	 * @param milestone
	 * @param createdBy
	 * @param notifyOpenTickets
	 * @return true if successful
	 * @since 1.6.0
	 */
	public synchronized boolean deleteMilestone(RepositoryModel repository, String milestone,
			String createdBy, boolean notifyOpenTickets) {
		if (StringUtils.isEmpty(milestone)) {
			throw new IllegalArgumentException("milestone can not be empty!");
		}
		Repository db = null;
		try {
			TicketMilestone tm = getMilestone(repository, milestone);
			if (tm == null) {
				return false;
			}
			db = repositoryManager.getRepository(repository.name);
			StoredConfig config = db.getConfig();
			config.unsetSection(MILESTONE, milestone);
			config.save();

			milestonesCache.remove(repository.name);

			TicketNotifier notifier = createNotifier();
			for (QueryResult qr : tm.tickets) {
				Change change = new Change(createdBy);
				change.setField(Field.milestone, "");
				TicketModel ticket = updateTicket(repository, qr.number, change);
				if (notifyOpenTickets && ticket.isOpen()) {
					notifier.queueMailing(ticket);
				}
			}
			if (notifyOpenTickets) {
				notifier.sendAll();
			}
			return true;
		} catch (IOException e) {
			log.error("failed to delete milestone " + milestone + " in " + repository, e);
		} finally {
			if (db != null) {
				db.close();
			}
		}
		return false;
	}

	/**
	 * Returns the set of assigned ticket ids in the repository.
	 *
	 * @param repository
	 * @return a set of assigned ticket ids in the repository
	 * @since 1.6.0
	 */
	public abstract Set<Long> getIds(RepositoryModel repository);

	/**
	 * Assigns a new ticket id.
	 *
	 * @param repository
	 * @return a new ticket id
	 * @since 1.4.0
	 */
	public abstract long assignNewId(RepositoryModel repository);

	/**
	 * Ensures that we have a ticket for this ticket id.
	 *
	 * @param repository
	 * @param ticketId
	 * @return true if the ticket exists
	 * @since 1.4.0
	 */
	public abstract boolean hasTicket(RepositoryModel repository, long ticketId);

	/**
	 * Returns all tickets.  This is not a Lucene search!
	 *
	 * @param repository
	 * @return all tickets
	 * @since 1.4.0
	 */
	public List<TicketModel> getTickets(RepositoryModel repository) {
		return getTickets(repository, null);
	}

	/**
	 * Returns all tickets that satisfy the filter. Retrieving tickets from the
	 * service requires deserializing all journals and building ticket models.
	 * This is an  expensive process and not recommended. Instead, the queryFor
	 * method should be used which executes against the Lucene index.
	 *
	 * @param repository
	 * @param filter
	 *            optional issue filter to only return matching results
	 * @return a list of tickets
	 * @since 1.4.0
	 */
	public abstract List<TicketModel> getTickets(RepositoryModel repository, TicketFilter filter);

	/**
	 * Retrieves the ticket.
	 *
	 * @param repository
	 * @param ticketId
	 * @return a ticket, if it exists, otherwise null
	 * @since 1.4.0
	 */
	public final TicketModel getTicket(RepositoryModel repository, long ticketId) {
		TicketKey key = new TicketKey(repository, ticketId);
		TicketModel ticket = ticketsCache.getIfPresent(key);

		// if ticket not cached
		if (ticket == null) {
			//load ticket
			ticket = getTicketImpl(repository, ticketId);
			// if ticket exists
			if (ticket != null) {
				if (ticket.hasPatchsets() && updateDiffstats) {
					Repository r = repositoryManager.getRepository(repository.name);
					try {
						Patchset patchset = ticket.getCurrentPatchset();
						DiffStat diffStat = DiffUtils.getDiffStat(r, patchset.base, patchset.tip);
						// diffstat could be null if we have ticket data without the
						// commit objects.  e.g. ticket replication without repo
						// mirroring
						if (diffStat != null) {
							ticket.insertions = diffStat.getInsertions();
							ticket.deletions = diffStat.getDeletions();
						}
					} finally {
						r.close();
					}
				}
				//cache ticket
				ticketsCache.put(key, ticket);
			}
		}
		return ticket;
	}

	/**
	 * Retrieves the ticket.
	 *
	 * @param repository
	 * @param ticketId
	 * @return a ticket, if it exists, otherwise null
	 * @since 1.4.0
	 */
	protected abstract TicketModel getTicketImpl(RepositoryModel repository, long ticketId);


	/**
	 * Returns the journal used to build a ticket.
	 *
	 * @param repository
	 * @param ticketId
	 * @return the journal for the ticket, if it exists, otherwise null
	 * @since 1.6.0
	 */
	public final List<Change> getJournal(RepositoryModel repository, long ticketId) {
		if (hasTicket(repository, ticketId)) {
			List<Change> journal = getJournalImpl(repository, ticketId);
			return journal;
		}
		return null;
	}

	/**
	 * Retrieves the ticket journal.
	 *
	 * @param repository
	 * @param ticketId
	 * @return a ticket, if it exists, otherwise null
	 * @since 1.6.0
	 */
	protected abstract List<Change> getJournalImpl(RepositoryModel repository, long ticketId);

	/**
	 * Get the ticket url
	 *
	 * @param ticket
	 * @return the ticket url
	 * @since 1.4.0
	 */
	public String getTicketUrl(TicketModel ticket) {
		final String canonicalUrl = settings.getString(Keys.web.canonicalUrl, "https://localhost:8443");
		final String hrefPattern = "{0}/tickets?r={1}&h={2,number,0}";
		return MessageFormat.format(hrefPattern, canonicalUrl, ticket.repository, ticket.number);
	}

	/**
	 * Get the compare url
	 *
	 * @param base
	 * @param tip
	 * @return the compare url
	 * @since 1.4.0
	 */
	public String getCompareUrl(TicketModel ticket, String base, String tip) {
		final String canonicalUrl = settings.getString(Keys.web.canonicalUrl, "https://localhost:8443");
		final String hrefPattern = "{0}/compare?r={1}&h={2}..{3}";
		return MessageFormat.format(hrefPattern, canonicalUrl, ticket.repository, base, tip);
	}

	/**
	 * Returns true if attachments are supported.
	 *
	 * @return true if attachments are supported
	 * @since 1.4.0
	 */
	public abstract boolean supportsAttachments();

	/**
	 * Retrieves the specified attachment from a ticket.
	 *
	 * @param repository
	 * @param ticketId
	 * @param filename
	 * @return an attachment, if found, null otherwise
	 * @since 1.4.0
	 */
	public abstract Attachment getAttachment(RepositoryModel repository, long ticketId, String filename);

	/**
	 * Creates a ticket.  Your change must include a repository, author & title,
	 * at a minimum. If your change does not have those minimum requirements a
	 * RuntimeException will be thrown.
	 *
	 * @param repository
	 * @param change
	 * @return true if successful
	 * @since 1.4.0
	 */
	public TicketModel createTicket(RepositoryModel repository, Change change) {
		return createTicket(repository, 0L, change);
	}

	/**
	 * Creates a ticket.  Your change must include a repository, author & title,
	 * at a minimum. If your change does not have those minimum requirements a
	 * RuntimeException will be thrown.
	 *
	 * @param repository
	 * @param ticketId (if <=0 the ticket id will be assigned)
	 * @param change
	 * @return true if successful
	 * @since 1.4.0
	 */
	public TicketModel createTicket(RepositoryModel repository, long ticketId, Change change) {

		if (repository == null) {
			throw new RuntimeException("Must specify a repository!");
		}
		if (StringUtils.isEmpty(change.author)) {
			throw new RuntimeException("Must specify a change author!");
		}
		if (!change.hasField(Field.title)) {
			throw new RuntimeException("Must specify a title!");
		}

		change.watch(change.author);

		if (ticketId <= 0L) {
			ticketId = assignNewId(repository);
		}

		change.setField(Field.status, Status.New);

		boolean success = commitChangeImpl(repository, ticketId, change);
		if (success) {
			TicketModel ticket = getTicket(repository, ticketId);
			indexer.index(ticket);

			// call the ticket hooks
			if (pluginManager != null) {
				for (TicketHook hook : pluginManager.getExtensions(TicketHook.class)) {
					try {
						hook.onNewTicket(ticket);
					} catch (Exception e) {
						log.error("Failed to execute extension", e);
					}
				}
			}
			return ticket;
		}
		return null;
	}

	/**
	 * Updates a ticket and promotes pending links into references.
	 *
	 * @param repository
	 * @param ticketId, or 0 to action pending links in general
	 * @param change
	 * @return the ticket model if successful, null if failure or using 0 ticketId
	 * @since 1.4.0
	 */
	public final TicketModel updateTicket(RepositoryModel repository, long ticketId, Change change) {
		if (change == null) {
			throw new RuntimeException("change can not be null!");
		}

		if (StringUtils.isEmpty(change.author)) {
			throw new RuntimeException("must specify a change author!");
		}

		boolean success = true;
		TicketModel ticket = null;
		
		if (ticketId > 0) {
			TicketKey key = new TicketKey(repository, ticketId);
			ticketsCache.invalidate(key);
	
			success = commitChangeImpl(repository, ticketId, change);
			
			if (success) {
				ticket = getTicket(repository, ticketId);
				ticketsCache.put(key, ticket);
				indexer.index(ticket);
	
				// call the ticket hooks
				if (pluginManager != null) {
					for (TicketHook hook : pluginManager.getExtensions(TicketHook.class)) {
						try {
							hook.onUpdateTicket(ticket, change);
						} catch (Exception e) {
							log.error("Failed to execute extension", e);
						}
					}
				}
			}
		}
		
		if (success) {
			//Now that the ticket has been successfully persisted add references to this ticket from linked tickets
			if (change.hasPendingLinks()) {
				for (TicketLink link : change.pendingLinks) {
					TicketModel linkedTicket = getTicket(repository, link.targetTicketId);
					Change dstChange = null;
					
					//Ignore if not available or self reference 
					if (linkedTicket != null && link.targetTicketId != ticketId) {
						dstChange = new Change(change.author, change.date);
						
						switch (link.action) {
							case Comment: {
								if (ticketId == 0) {
									throw new RuntimeException("must specify a ticket when linking a comment!");
								}
								dstChange.referenceTicket(ticketId, change.comment.id);
							} break;
							
							case Commit: {
								dstChange.referenceCommit(link.hash);
							} break;
							
							default: {
								throw new RuntimeException(
										String.format("must add persist logic for link of type %s", link.action));
							}
						}
					}
					
					if (dstChange != null) {
						//If not deleted then remain null in journal
						if (link.isDelete) {
							dstChange.reference.deleted = true;
						}

						if (updateTicket(repository, link.targetTicketId, dstChange) != null) {
							link.success = true;
						}
					}
				}
			}
		}
		
		return ticket;
	}

	/**
	 * Deletes all tickets in every repository.
	 *
	 * @return true if successful
	 * @since 1.4.0
	 */
	public boolean deleteAll() {
		List<String> repositories = repositoryManager.getRepositoryList();
		BitSet bitset = new BitSet(repositories.size());
		for (int i = 0; i < repositories.size(); i++) {
			String name = repositories.get(i);
			RepositoryModel repository = repositoryManager.getRepositoryModel(name);
			boolean success = deleteAll(repository);
			bitset.set(i, success);
		}
		boolean success = bitset.cardinality() == repositories.size();
		if (success) {
			indexer.deleteAll();
			resetCaches();
		}
		return success;
	}

	/**
	 * Deletes all tickets in the specified repository.
	 * @param repository
	 * @return true if succesful
	 * @since 1.4.0
	 */
	public boolean deleteAll(RepositoryModel repository) {
		boolean success = deleteAllImpl(repository);
		if (success) {
			log.info("Deleted all tickets for {}", repository.name);
			resetCaches(repository);
			indexer.deleteAll(repository);
		}
		return success;
	}

	/**
	 * Delete all tickets for the specified repository.
	 * @param repository
	 * @return true if successful
	 * @since 1.4.0
	 */
	protected abstract boolean deleteAllImpl(RepositoryModel repository);

	/**
	 * Handles repository renames.
	 *
	 * @param oldRepositoryName
	 * @param newRepositoryName
	 * @return true if successful
	 * @since 1.4.0
	 */
	public boolean rename(RepositoryModel oldRepository, RepositoryModel newRepository) {
		if (renameImpl(oldRepository, newRepository)) {
			resetCaches(oldRepository);
			indexer.deleteAll(oldRepository);
			reindex(newRepository);
			return true;
		}
		return false;
	}

	/**
	 * Renames a repository.
	 *
	 * @param oldRepository
	 * @param newRepository
	 * @return true if successful
	 * @since 1.4.0
	 */
	protected abstract boolean renameImpl(RepositoryModel oldRepository, RepositoryModel newRepository);

	/**
	 * Deletes a ticket.
	 *
	 * @param repository
	 * @param ticketId
	 * @param deletedBy
	 * @return true if successful
	 * @since 1.4.0
	 */
	public boolean deleteTicket(RepositoryModel repository, long ticketId, String deletedBy) {
		TicketModel ticket = getTicket(repository, ticketId);
		boolean success = deleteTicketImpl(repository, ticket, deletedBy);
		if (success) {
			log.info(MessageFormat.format("Deleted {0} ticket #{1,number,0}: {2}",
					repository.name, ticketId, ticket.title));
			ticketsCache.invalidate(new TicketKey(repository, ticketId));
			indexer.delete(ticket);
			return true;
		}
		return false;
	}

	/**
	 * Deletes a ticket.
	 *
	 * @param repository
	 * @param ticket
	 * @param deletedBy
	 * @return true if successful
	 * @since 1.4.0
	 */
	protected abstract boolean deleteTicketImpl(RepositoryModel repository, TicketModel ticket, String deletedBy);


	/**
	 * Updates the text of an ticket comment.
	 *
	 * @param ticket
	 * @param commentId
	 *            the id of the comment to revise
	 * @param updatedBy
	 *            the author of the updated comment
	 * @param comment
	 *            the revised comment
	 * @return the revised ticket if the change was successful
	 * @since 1.4.0
	 */
	public final TicketModel updateComment(TicketModel ticket, String commentId,
			String updatedBy, String comment) {
		Change revision = new Change(updatedBy);
		revision.comment(comment);
		revision.comment.id = commentId;
		RepositoryModel repository = repositoryManager.getRepositoryModel(ticket.repository);
		TicketModel revisedTicket = updateTicket(repository, ticket.number, revision);
		return revisedTicket;
	}

	/**
	 * Deletes a comment from a ticket.
	 *
	 * @param ticket
	 * @param commentId
	 *            the id of the comment to delete
	 * @param deletedBy
	 * 			the user deleting the comment
	 * @return the revised ticket if the deletion was successful
	 * @since 1.4.0
	 */
	public final TicketModel deleteComment(TicketModel ticket, String commentId, String deletedBy) {
		Change deletion = new Change(deletedBy);
		deletion.comment("");
		deletion.comment.id = commentId;
		deletion.comment.deleted = true;
		RepositoryModel repository = repositoryManager.getRepositoryModel(ticket.repository);
		TicketModel revisedTicket = updateTicket(repository, ticket.number, deletion);
		return revisedTicket;
	}
	
	/**
	 * Deletes a patchset from a ticket.
	 *
	 * @param ticket
	 * @param patchset
	 *            the patchset to delete (should be the highest revision)
	 * @param userName
	 * 			the user deleting the commit
	 * @return the revised ticket if the deletion was successful
	 * @since 1.8.0
	 */
	public final TicketModel deletePatchset(TicketModel ticket, Patchset patchset, String userName) {
		Change deletion = new Change(userName);
		deletion.patchset = new Patchset();
		deletion.patchset.number = patchset.number;
		deletion.patchset.rev = patchset.rev;
		deletion.patchset.type = PatchsetType.Delete;
		//Find and delete references to tickets by the removed commits
		List<TicketLink> patchsetTicketLinks = JGitUtils.identifyTicketsBetweenCommits(
				repositoryManager.getRepository(ticket.repository),
				settings, patchset.base, patchset.tip);
		
		for (TicketLink link : patchsetTicketLinks) {
			link.isDelete = true;
		}
		deletion.pendingLinks = patchsetTicketLinks;
		
		RepositoryModel repositoryModel = repositoryManager.getRepositoryModel(ticket.repository);
		TicketModel revisedTicket = updateTicket(repositoryModel, ticket.number, deletion);
		
		return revisedTicket;
	} 

	/**
	 * Commit a ticket change to the repository.
	 *
	 * @param repository
	 * @param ticketId
	 * @param change
	 * @return true, if the change was committed
	 * @since 1.4.0
	 */
	protected abstract boolean commitChangeImpl(RepositoryModel repository, long ticketId, Change change);


	/**
	 * Searches for the specified text.  This will use the indexer, if available,
	 * or will fall back to brute-force retrieval of all tickets and string
	 * matching.
	 *
	 * @param repository
	 * @param text
	 * @param page
	 * @param pageSize
	 * @return a list of matching tickets
	 * @since 1.4.0
	 */
	public List<QueryResult> searchFor(RepositoryModel repository, String text, int page, int pageSize) {
		return indexer.searchFor(repository, text, page, pageSize);
	}

	/**
	 * Queries the index for the matching tickets.
	 *
	 * @param query
	 * @param page
	 * @param pageSize
	 * @param sortBy
	 * @param descending
	 * @return a list of matching tickets or an empty list
	 * @since 1.4.0
	 */
	public List<QueryResult> queryFor(String query, int page, int pageSize, String sortBy, boolean descending) {
		return indexer.queryFor(query, page, pageSize, sortBy, descending);
	}


	/**
	 * Checks tickets should get re-indexed.
	 *
	 * @return true if tickets should get re-indexed, false otherwise.
	 */
	private boolean shouldReindex()
	{
		return indexer.shouldReindex();
	}


	/**
	 * Destroys an existing index and reindexes all tickets.
	 * This operation may be expensive and time-consuming.
	 * @since 1.4.0
	 */
	public void reindex() {
		long start = System.nanoTime();
		indexer.deleteAll();
		for (String name : repositoryManager.getRepositoryList()) {
			RepositoryModel repository = repositoryManager.getRepositoryModel(name);
			try {
			List<TicketModel> tickets = getTickets(repository);
			if (!tickets.isEmpty()) {
				log.info("reindexing {} tickets from {} ...", tickets.size(), repository);
				indexer.index(tickets);
				System.gc();
			}
			} catch (Exception e) {
				log.error("failed to reindex {}", repository.name);
				log.error(null, e);
			}
		}
		long end = System.nanoTime();
		long secs = TimeUnit.NANOSECONDS.toMillis(end - start);
		log.info("reindexing completed in {} msecs.", secs);
	}

	/**
	 * Destroys any existing index and reindexes all tickets.
	 * This operation may be expensive and time-consuming.
	 * @since 1.4.0
	 */
	public void reindex(RepositoryModel repository) {
		long start = System.nanoTime();
		List<TicketModel> tickets = getTickets(repository);
		indexer.index(tickets);
		log.info("reindexing {} tickets from {} ...", tickets.size(), repository);
		long end = System.nanoTime();
		long secs = TimeUnit.NANOSECONDS.toMillis(end - start);
		log.info("reindexing completed in {} msecs.", secs);
		resetCaches(repository);
	}

	/**
	 * Synchronously executes the runnable. This is used for special processing
	 * of ticket updates, namely merging from the web ui.
	 *
	 * @param runnable
	 * @since 1.4.0
	 */
	public synchronized void exec(Runnable runnable) {
		runnable.run();
	}
}
