/*
 * Copyright 2014 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.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

import org.eclipse.jgit.lib.Repository;

import com.gitblit.Constants;
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.utils.ArrayUtils;
import com.gitblit.utils.FileUtils;
import com.gitblit.utils.StringUtils;
import com.google.inject.Inject;
import com.google.inject.Singleton;

/**
 * Implementation of a ticket service based on a directory within the repository.
 * All tickets are serialized as a list of JSON changes and persisted in a hashed
 * directory structure, similar to the standard git loose object structure.
 *
 * @author James Moger
 *
 */
@Singleton
public class FileTicketService extends ITicketService {

	private static final String JOURNAL = "journal.json";

	private static final String TICKETS_PATH = "tickets/";

	private final Map<String, AtomicLong> lastAssignedId;

	@Inject
	public FileTicketService(
			IRuntimeManager runtimeManager,
			IPluginManager pluginManager,
			INotificationManager notificationManager,
			IUserManager userManager,
			IRepositoryManager repositoryManager) {

		super(runtimeManager,
				pluginManager,
				notificationManager,
				userManager,
				repositoryManager);

		lastAssignedId = new ConcurrentHashMap<String, AtomicLong>();
	}

	@Override
	public FileTicketService start() {
		log.info("{} started", getClass().getSimpleName());
		return this;
	}

	@Override
	protected void resetCachesImpl() {
		lastAssignedId.clear();
	}

	@Override
	protected void resetCachesImpl(RepositoryModel repository) {
		if (lastAssignedId.containsKey(repository.name)) {
			lastAssignedId.get(repository.name).set(0);
		}
	}

	@Override
	protected void close() {
	}

	/**
	 * Returns the ticket path. This follows the same scheme as Git's object
	 * store path where the first two characters of the hash id are the root
	 * folder with the remaining characters as a subfolder within that folder.
	 *
	 * @param ticketId
	 * @return the root path of the ticket content in the ticket directory
	 */
	private String toTicketPath(long ticketId) {
		StringBuilder sb = new StringBuilder();
		sb.append(TICKETS_PATH);
		long m = ticketId % 100L;
		if (m < 10) {
			sb.append('0');
		}
		sb.append(m);
		sb.append('/');
		sb.append(ticketId);
		return sb.toString();
	}

	/**
	 * Returns the path to the attachment for the specified ticket.
	 *
	 * @param ticketId
	 * @param filename
	 * @return the path to the specified attachment
	 */
	private String toAttachmentPath(long ticketId, String filename) {
		return toTicketPath(ticketId) + "/attachments/" + filename;
	}

	/**
	 * Ensures that we have a ticket for this ticket id.
	 *
	 * @param repository
	 * @param ticketId
	 * @return true if the ticket exists
	 */
	@Override
	public boolean hasTicket(RepositoryModel repository, long ticketId) {
		boolean hasTicket = false;
		Repository db = repositoryManager.getRepository(repository.name);
		try {
			String journalPath = toTicketPath(ticketId) + "/" + JOURNAL;
			hasTicket = new File(db.getDirectory(), journalPath).exists();
		} finally {
			db.close();
		}
		return hasTicket;
	}

	@Override
	public synchronized Set<Long> getIds(RepositoryModel repository) {
		Set<Long> ids = new TreeSet<Long>();
		Repository db = repositoryManager.getRepository(repository.name);
		try {
			// identify current highest ticket id by scanning the paths in the tip tree
			File dir = new File(db.getDirectory(), TICKETS_PATH);
			dir.mkdirs();
			List<File> journals = findAll(dir, JOURNAL);
			for (File journal : journals) {
				// Reconstruct ticketId from the path
				// id/26/326/journal.json
				String path = FileUtils.getRelativePath(dir, journal);
				String tid = path.split("/")[1];
				long ticketId = Long.parseLong(tid);
				ids.add(ticketId);
			}
		} finally {
			if (db != null) {
				db.close();
			}
		}
		return ids;
	}

	/**
	 * Assigns a new ticket id.
	 *
	 * @param repository
	 * @return a new long id
	 */
	@Override
	public synchronized long assignNewId(RepositoryModel repository) {
		long newId = 0L;
		Repository db = repositoryManager.getRepository(repository.name);
		try {
			if (!lastAssignedId.containsKey(repository.name)) {
				lastAssignedId.put(repository.name, new AtomicLong(0));
			}
			AtomicLong lastId = lastAssignedId.get(repository.name);
			if (lastId.get() <= 0) {
				Set<Long> ids = getIds(repository);
				for (long id : ids) {
					if (id > lastId.get()) {
						lastId.set(id);
					}
				}
			}

			// assign the id and touch an empty journal to hold it's place
			newId = lastId.incrementAndGet();
			String journalPath = toTicketPath(newId) + "/" + JOURNAL;
			File journal = new File(db.getDirectory(), journalPath);
			journal.getParentFile().mkdirs();
			journal.createNewFile();
		} catch (IOException e) {
			log.error("failed to assign ticket id", e);
			return 0L;
		} finally {
			db.close();
		}
		return newId;
	}

	/**
	 * Returns all the tickets in the repository. Querying tickets from the
	 * repository requires deserializing all tickets. This is an  expensive
	 * process and not recommended. Tickets are indexed by Lucene and queries
	 * should be executed against that index.
	 *
	 * @param repository
	 * @param filter
	 *            optional filter to only return matching results
	 * @return a list of tickets
	 */
	@Override
	public List<TicketModel> getTickets(RepositoryModel repository, TicketFilter filter) {
		List<TicketModel> list = new ArrayList<TicketModel>();

		Repository db = repositoryManager.getRepository(repository.name);
		try {
			// Collect the set of all json files
			File dir = new File(db.getDirectory(), TICKETS_PATH);
			List<File> journals = findAll(dir, JOURNAL);

			// Deserialize each ticket and optionally filter out unwanted tickets
			for (File journal : journals) {
				String json = null;
				try {
					json = new String(FileUtils.readContent(journal), Constants.ENCODING);
				} catch (Exception e) {
					log.error(null, e);
				}
				if (StringUtils.isEmpty(json)) {
					// journal was touched but no changes were written
					continue;
				}
				try {
					// Reconstruct ticketId from the path
					// id/26/326/journal.json
					String path = FileUtils.getRelativePath(dir, journal);
					String tid = path.split("/")[1];
					long ticketId = Long.parseLong(tid);
					List<Change> changes = TicketSerializer.deserializeJournal(json);
					if (ArrayUtils.isEmpty(changes)) {
						log.warn("Empty journal for {}:{}", repository, journal);
						continue;
					}
					TicketModel ticket = TicketModel.buildTicket(changes);
					ticket.project = repository.projectPath;
					ticket.repository = repository.name;
					ticket.number = ticketId;

					// add the ticket, conditionally, to the list
					if (filter == null) {
						list.add(ticket);
					} else {
						if (filter.accept(ticket)) {
							list.add(ticket);
						}
					}
				} catch (Exception e) {
					log.error("failed to deserialize {}/{}\n{}",
							new Object [] { repository, journal, e.getMessage()});
					log.error(null, e);
				}
			}

			// sort the tickets by creation
			Collections.sort(list);
			return list;
		} finally {
			db.close();
		}
	}

	private List<File> findAll(File dir, String filename) {
		List<File> list = new ArrayList<File>();
		File [] files = dir.listFiles();
		if (files == null) {
			return list;
		}
		for (File file : files) {
			if (file.isDirectory()) {
				list.addAll(findAll(file, filename));
			} else if (file.isFile()) {
				if (file.getName().equalsIgnoreCase(filename)) {
					list.add(file);
				}
			}
		}
		return list;
	}

	/**
	 * Retrieves the ticket from the repository.
	 *
	 * @param repository
	 * @param ticketId
	 * @return a ticket, if it exists, otherwise null
	 */
	@Override
	protected TicketModel getTicketImpl(RepositoryModel repository, long ticketId) {
		Repository db = repositoryManager.getRepository(repository.name);
		try {
			List<Change> changes = getJournal(db, ticketId);
			if (ArrayUtils.isEmpty(changes)) {
				log.warn("Empty journal for {}:{}", repository, ticketId);
				return null;
			}
			TicketModel ticket = TicketModel.buildTicket(changes);
			if (ticket != null) {
				ticket.project = repository.projectPath;
				ticket.repository = repository.name;
				ticket.number = ticketId;
			}
			return ticket;
		} finally {
			db.close();
		}
	}

	/**
	 * Retrieves the journal for the ticket.
	 *
	 * @param repository
	 * @param ticketId
	 * @return a journal, if it exists, otherwise null
	 */
	@Override
	protected List<Change> getJournalImpl(RepositoryModel repository, long ticketId) {
		Repository db = repositoryManager.getRepository(repository.name);
		try {
			List<Change> changes = getJournal(db, ticketId);
			if (ArrayUtils.isEmpty(changes)) {
				log.warn("Empty journal for {}:{}", repository, ticketId);
				return null;
			}
			return changes;
		} finally {
			db.close();
		}
	}

	/**
	 * Returns the journal for the specified ticket.
	 *
	 * @param db
	 * @param ticketId
	 * @return a list of changes
	 */
	private List<Change> getJournal(Repository db, long ticketId) {
		if (ticketId <= 0L) {
			return new ArrayList<Change>();
		}

		String journalPath = toTicketPath(ticketId) + "/" + JOURNAL;
		File journal = new File(db.getDirectory(), journalPath);
		if (!journal.exists()) {
			return new ArrayList<Change>();
		}

		String json = null;
		try {
			json = new String(FileUtils.readContent(journal), Constants.ENCODING);
		} catch (Exception e) {
			log.error(null, e);
		}
		if (StringUtils.isEmpty(json)) {
			return new ArrayList<Change>();
		}
		List<Change> list = TicketSerializer.deserializeJournal(json);
		return list;
	}

	@Override
	public boolean supportsAttachments() {
		return true;
	}

	/**
	 * Retrieves the specified attachment from a ticket.
	 *
	 * @param repository
	 * @param ticketId
	 * @param filename
	 * @return an attachment, if found, null otherwise
	 */
	@Override
	public Attachment getAttachment(RepositoryModel repository, long ticketId, String filename) {
		if (ticketId <= 0L) {
			return null;
		}

		// deserialize the ticket model so that we have the attachment metadata
		TicketModel ticket = getTicket(repository, ticketId);
		Attachment attachment = ticket.getAttachment(filename);

		// attachment not found
		if (attachment == null) {
			return null;
		}

		// retrieve the attachment content
		Repository db = repositoryManager.getRepository(repository.name);
		try {
			String attachmentPath = toAttachmentPath(ticketId, attachment.name);
			File file = new File(db.getDirectory(), attachmentPath);
			if (file.exists()) {
				attachment.content = FileUtils.readContent(file);
				attachment.size = attachment.content.length;
			}
			return attachment;
		} finally {
			db.close();
		}
	}

	/**
	 * Deletes a ticket from the repository.
	 *
	 * @param ticket
	 * @return true if successful
	 */
	@Override
	protected synchronized boolean deleteTicketImpl(RepositoryModel repository, TicketModel ticket, String deletedBy) {
		if (ticket == null) {
			throw new RuntimeException("must specify a ticket!");
		}

		boolean success = false;
		Repository db = repositoryManager.getRepository(ticket.repository);
		try {
			String ticketPath = toTicketPath(ticket.number);
			File dir = new File(db.getDirectory(), ticketPath);
			if (dir.exists()) {
				success = FileUtils.delete(dir);
			}
			success = true;
		} finally {
			db.close();
		}
		return success;
	}

	/**
	 * Commit a ticket change to the repository.
	 *
	 * @param repository
	 * @param ticketId
	 * @param change
	 * @return true, if the change was committed
	 */
	@Override
	protected synchronized boolean commitChangeImpl(RepositoryModel repository, long ticketId, Change change) {
		boolean success = false;

		Repository db = repositoryManager.getRepository(repository.name);
		try {
			List<Change> changes = getJournal(db, ticketId);
			changes.add(change);
			String journal = TicketSerializer.serializeJournal(changes).trim();

			String journalPath = toTicketPath(ticketId) + "/" + JOURNAL;
			File file = new File(db.getDirectory(), journalPath);
			file.getParentFile().mkdirs();
			FileUtils.writeContent(file, journal);
			success = true;
		} catch (Throwable t) {
			log.error(MessageFormat.format("Failed to commit ticket {0,number,0} to {1}",
					ticketId, db.getDirectory()), t);
		} finally {
			db.close();
		}
		return success;
	}

	@Override
	protected boolean deleteAllImpl(RepositoryModel repository) {
		Repository db = repositoryManager.getRepository(repository.name);
		if (db == null) {
			// the tickets no longer exist because the db no longer exists
			return true;
		}
		try {
			File dir = new File(db.getDirectory(), TICKETS_PATH);
			return FileUtils.delete(dir);
		} catch (Exception e) {
			log.error(null, e);
		} finally {
			db.close();
		}
		return false;
	}

	@Override
	protected boolean renameImpl(RepositoryModel oldRepository, RepositoryModel newRepository) {
		return true;
	}

	@Override
	public String toString() {
		return getClass().getSimpleName();
	}
}
