/*
 * 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.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.eclipse.jgit.diff.DiffEntry.ChangeType;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.slf4j.LoggerFactory;

import com.gitblit.Constants;
import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.git.PatchsetCommand;
import com.gitblit.manager.INotificationManager;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.manager.IUserManager;
import com.gitblit.models.Mailing;
import com.gitblit.models.Owner;
import com.gitblit.models.PathModel.PathChangeModel;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.TicketModel;
import com.gitblit.models.TicketModel.Change;
import com.gitblit.models.TicketModel.Field;
import com.gitblit.models.TicketModel.Patchset;
import com.gitblit.models.TicketModel.Review;
import com.gitblit.models.TicketModel.Status;
import com.gitblit.models.UserModel;
import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.DiffUtils;
import com.gitblit.utils.DiffUtils.DiffStat;
import com.gitblit.utils.JGitUtils;
import com.gitblit.utils.MarkdownUtils;
import com.gitblit.utils.StringUtils;

/**
 * Formats and queues ticket/patch notifications for dispatch to the
 * mail executor upon completion of a push or a ticket update.  Messages are
 * created as Markdown and then transformed to html.
 *
 * @author James Moger
 *
 */
public class TicketNotifier {

	protected final Map<Long, Mailing> queue = new TreeMap<Long, Mailing>();

	private final String SOFT_BRK = "\n";

	private final String HARD_BRK = "\n\n";

	private final String HR = "----\n\n";

	private final IStoredSettings settings;

	private final INotificationManager notificationManager;

	private final IUserManager userManager;

	private final IRepositoryManager repositoryManager;

	private final ITicketService ticketService;

	private final String addPattern = "<span style=\"color:darkgreen;\">+{0}</span>";
	private final String delPattern = "<span style=\"color:darkred;\">-{0}</span>";

	public TicketNotifier(
			IRuntimeManager runtimeManager,
			INotificationManager notificationManager,
			IUserManager userManager,
			IRepositoryManager repositoryManager,
			ITicketService ticketService) {

		this.settings = runtimeManager.getSettings();
		this.notificationManager = notificationManager;
		this.userManager = userManager;
		this.repositoryManager = repositoryManager;
		this.ticketService = ticketService;
	}

	public void sendAll() {
		for (Mailing mail : queue.values()) {
			notificationManager.send(mail);
		}
	}

	public void sendMailing(TicketModel ticket) {
		queueMailing(ticket);
		sendAll();
	}

	/**
	 * Queues an update notification.
	 *
	 * @param ticket
	 * @return a notification object used for testing
	 */
	public Mailing queueMailing(TicketModel ticket) {
		try {
			// format notification message
			String markdown = formatLastChange(ticket);

			StringBuilder html = new StringBuilder();
			html.append("<head>");
			html.append(readStyle());
			html.append("</head>");
			html.append("<body>");
			html.append(MarkdownUtils.transformGFM(settings, markdown, ticket.repository));
			html.append("</body>");

			Mailing mailing = Mailing.newHtml();
			mailing.from = getUserModel(ticket.updatedBy == null ? ticket.createdBy : ticket.updatedBy).getDisplayName();
			mailing.subject = getSubject(ticket);
			mailing.content = html.toString();
			mailing.id = "ticket." + ticket.number + "." + StringUtils.getSHA1(ticket.repository + ticket.number);

			setRecipients(ticket, mailing);
			queue.put(ticket.number, mailing);

			return mailing;
		} catch (Exception e) {
			Logger.getLogger(getClass()).error("failed to queue mailing for #" + ticket.number, e);
		}
		return null;
	}

	protected String getSubject(TicketModel ticket) {
		Change lastChange = ticket.changes.get(ticket.changes.size() - 1);
		boolean newTicket = lastChange.isStatusChange() && ticket.changes.size() == 1;
		String re = newTicket ? "" : "Re: ";
		String subject = MessageFormat.format("{0}[{1}] {2} (#{3,number,0})",
				re, StringUtils.stripDotGit(ticket.repository), ticket.title, ticket.number);
		return subject;
	}

	protected String formatLastChange(TicketModel ticket) {
		Change lastChange = ticket.changes.get(ticket.changes.size() - 1);
		UserModel user = getUserModel(lastChange.author);

		// define the fields we do NOT want to see in an email notification
		Set<TicketModel.Field> fieldExclusions = new HashSet<TicketModel.Field>();
		fieldExclusions.addAll(Arrays.asList(Field.watchers, Field.voters));

		StringBuilder sb = new StringBuilder();
		boolean newTicket = lastChange.isStatusChange() && Status.New == lastChange.getStatus();
		boolean isFastForward = true;
		List<RevCommit> commits = null;
		DiffStat diffstat = null;

		String pattern;
		if (lastChange.hasPatchset()) {
			// patchset uploaded
			Patchset patchset = lastChange.patchset;
			String base = "";
			// determine the changed paths
			Repository repo = null;
			try {
				repo = repositoryManager.getRepository(ticket.repository);
				if (patchset.isFF() && (patchset.rev > 1)) {
					// fast-forward update, just show the new data
					isFastForward = true;
					Patchset prev = ticket.getPatchset(patchset.number, patchset.rev - 1);
					base = prev.tip;
				} else {
					// proposal OR non-fast-forward update
					isFastForward = false;
					base = patchset.base;
				}

				diffstat = DiffUtils.getDiffStat(repo, base, patchset.tip);
				commits = JGitUtils.getRevLog(repo, base, patchset.tip);
			} catch (Exception e) {
				Logger.getLogger(getClass()).error("failed to get changed paths", e);
			} finally {
				if (repo != null) {
					repo.close();
				}
			}

			String compareUrl = ticketService.getCompareUrl(ticket, base, patchset.tip);

			if (newTicket) {
				// new proposal
				pattern = "**{0}** is proposing a change.";
				sb.append(MessageFormat.format(pattern, user.getDisplayName()));
				fieldExclusions.add(Field.status);
				fieldExclusions.add(Field.title);
				fieldExclusions.add(Field.body);
			} else {
				// describe the patchset
				if (patchset.isFF()) {
					pattern = "**{0}** added {1} {2} to patchset {3}.";
					sb.append(MessageFormat.format(pattern, user.getDisplayName(), patchset.added, patchset.added == 1 ? "commit" : "commits", patchset.number));
				} else {
					pattern = "**{0}** uploaded patchset {1}. *({2})*";
					sb.append(MessageFormat.format(pattern, user.getDisplayName(), patchset.number, patchset.type.toString().toUpperCase()));
				}
			}
			sb.append(HARD_BRK);

			sb.append(MessageFormat.format("{0} {1}, {2} {3}, <span style=\"color:darkgreen;\">+{4} insertions</span>, <span style=\"color:darkred;\">-{5} deletions</span> from {6}. [compare]({7})",
					commits.size(), commits.size() == 1 ? "commit" : "commits",
					diffstat.paths.size(),
					diffstat.paths.size() == 1 ? "file" : "files",
					diffstat.getInsertions(),
					diffstat.getDeletions(),
					isFastForward ? "previous revision" : "merge base",
					compareUrl));

			// note commit additions on a rebase,if any
			switch (lastChange.patchset.type) {
			case Rebase:
				if (lastChange.patchset.added > 0) {
					sb.append(SOFT_BRK);
					sb.append(MessageFormat.format("{0} {1} added.", lastChange.patchset.added, lastChange.patchset.added == 1 ? "commit" : "commits"));
				}
				break;
			default:
				break;
			}
			sb.append(HARD_BRK);
		} else if (lastChange.isStatusChange()) {
			if (newTicket) {
				fieldExclusions.add(Field.status);
				fieldExclusions.add(Field.title);
				fieldExclusions.add(Field.body);
				pattern = "**{0}** created this ticket.";
				sb.append(MessageFormat.format(pattern, user.getDisplayName()));
			} else if (lastChange.hasField(Field.mergeSha)) {
				// closed by merged
				pattern = "**{0}** closed this ticket by merging {1} to {2}.";

				// identify patchset that closed the ticket
				String merged = ticket.mergeSha;
				for (Patchset patchset : ticket.getPatchsets()) {
					if (patchset.tip.equals(ticket.mergeSha)) {
						merged = patchset.toString();
						break;
					}
				}
				sb.append(MessageFormat.format(pattern, user.getDisplayName(), merged, ticket.mergeTo));
			} else {
				// workflow status change by user
				pattern = "**{0}** changed the status of this ticket to **{1}**.";
				sb.append(MessageFormat.format(pattern, user.getDisplayName(), lastChange.getStatus().toString().toUpperCase()));
			}
			sb.append(HARD_BRK);
		} else if (lastChange.hasReview()) {
			// review
			Review review = lastChange.review;
			pattern = "**{0}** has reviewed patchset {1,number,0} revision {2,number,0}.";
			sb.append(MessageFormat.format(pattern, user.getDisplayName(), review.patchset, review.rev));
			sb.append(HARD_BRK);

			String d = settings.getString(Keys.web.datestampShortFormat, "yyyy-MM-dd");
			String t = settings.getString(Keys.web.timeFormat, "HH:mm");
			DateFormat df = new SimpleDateFormat(d + " " + t);
			List<Change> reviews = ticket.getReviews(ticket.getPatchset(review.patchset, review.rev));
			sb.append("| Date | Reviewer      | Score | Description  |\n");
			sb.append("| :--- | :------------ | :---: | :----------- |\n");
			for (Change change : reviews) {
				String name = change.author;
				UserModel u = userManager.getUserModel(change.author);
				if (u != null) {
					name = u.getDisplayName();
				}
				String score;
				switch (change.review.score) {
				case approved:
					score = MessageFormat.format(addPattern, change.review.score.getValue());
					break;
				case vetoed:
					score = MessageFormat.format(delPattern, Math.abs(change.review.score.getValue()));
					break;
				default:
					score = "" + change.review.score.getValue();
				}
				String date = df.format(change.date);
				sb.append(String.format("| %1$s | %2$s | %3$s | %4$s |\n",
						date, name, score, change.review.score.toString()));
			}
			sb.append(HARD_BRK);
		} else if (lastChange.hasComment()) {
			// comment update
			sb.append(MessageFormat.format("**{0}** commented on this ticket.", user.getDisplayName()));
			sb.append(HARD_BRK);
		} else {
			// general update
			pattern = "**{0}** has updated this ticket.";
			sb.append(MessageFormat.format(pattern, user.getDisplayName()));
			sb.append(HARD_BRK);
		}

		// ticket link
		sb.append(MessageFormat.format("[view ticket {0,number,0}]({1})",
				ticket.number, ticketService.getTicketUrl(ticket)));
		sb.append(HARD_BRK);

		if (newTicket) {
			// ticket title
			sb.append(MessageFormat.format("### {0}", ticket.title));
			sb.append(HARD_BRK);

			// ticket description, on state change
			if (StringUtils.isEmpty(ticket.body)) {
				sb.append("<span style=\"color: #888;\">no description entered</span>");
			} else {
				sb.append(ticket.body);
			}
			sb.append(HARD_BRK);
			sb.append(HR);
		}

		// field changes
		if (lastChange.hasFieldChanges()) {
			Map<Field, String> filtered = new HashMap<Field, String>();
			for (Map.Entry<Field, String> fc : lastChange.fields.entrySet()) {
				if (!fieldExclusions.contains(fc.getKey())) {
					// field is included
					filtered.put(fc.getKey(), fc.getValue());
				}
			}

			// sort by field ordinal
			List<Field> fields = new ArrayList<Field>(filtered.keySet());
			Collections.sort(fields);

			if (filtered.size() > 0) {
				sb.append(HARD_BRK);
				sb.append("| Field Changes               ||\n");
				sb.append("| ------------: | :----------- |\n");
				for (Field field : fields) {
					String value;
					if (filtered.get(field) == null) {
						value = "";
					} else {
						value = filtered.get(field).replace("\r\n", "<br/>").replace("\n", "<br/>").replace("|", "&#124;");
					}
					sb.append(String.format("| **%1$s:** | %2$s |\n", field.name(), value));
				}
				sb.append(HARD_BRK);
			}
		}

		// new comment
		if (lastChange.hasComment()) {
			sb.append(HR);
			sb.append(lastChange.comment.text);
			sb.append(HARD_BRK);
		}

		// insert the patchset details and review instructions
		if (lastChange.hasPatchset() && ticket.isOpen()) {
			if (commits != null && commits.size() > 0) {
				// append the commit list
				String title = isFastForward ? "Commits added to previous patchset revision" : "All commits in patchset";
				sb.append(MessageFormat.format("| {0} |||\n", title));
				sb.append("| SHA | Author | Title |\n");
				sb.append("| :-- | :----- | :---- |\n");
				for (RevCommit commit : commits) {
					sb.append(MessageFormat.format("| {0} | {1} | {2} |\n",
							commit.getName(), commit.getAuthorIdent().getName(),
							StringUtils.trimString(commit.getShortMessage(), Constants.LEN_SHORTLOG).replace("|", "&#124;")));
				}
				sb.append(HARD_BRK);
			}

			if (diffstat != null) {
				// append the changed path list
				String title = isFastForward ? "Files changed since previous patchset revision" : "All files changed in patchset";
				sb.append(MessageFormat.format("| {0} |||\n", title));
				sb.append("| :-- | :----------- | :-: |\n");
				for (PathChangeModel path : diffstat.paths) {
					String add = MessageFormat.format(addPattern, path.insertions);
					String del = MessageFormat.format(delPattern, path.deletions);
					String diff = null;
					switch (path.changeType) {
					case ADD:
						diff = add;
						break;
					case DELETE:
						diff = del;
						break;
					case MODIFY:
						if (path.insertions > 0 && path.deletions > 0) {
							// insertions & deletions
							diff = add + "/" + del;
						} else if (path.insertions > 0) {
							// just insertions
							diff = add;
						} else {
							// just deletions
							diff = del;
						}
						break;
					default:
						diff = path.changeType.name();
						break;
					}
					sb.append(MessageFormat.format("| {0} | {1} | {2} |\n",
							getChangeType(path.changeType), path.name, diff));
				}
				sb.append(HARD_BRK);
			}

			sb.append(formatPatchsetInstructions(ticket, lastChange.patchset));
		}

		return sb.toString();
	}

	protected String getChangeType(ChangeType type) {
		String style = null;
		switch (type) {
			case ADD:
				style = "color:darkgreen;";
				break;
			case COPY:
				style = "";
				break;
			case DELETE:
				style = "color:darkred;";
				break;
			case MODIFY:
				style = "";
				break;
			case RENAME:
				style = "";
				break;
			default:
				break;
		}
		String code = type.name().toUpperCase().substring(0, 1);
		if (style == null) {
			return code;
		} else {
			return MessageFormat.format("<strong><span style=\"{0}padding:2px;margin:2px;border:1px solid #ddd;\">{1}</span></strong>", style, code);
		}
	}

	/**
	 * Generates patchset review instructions for command-line git
	 *
	 * @param patchset
	 * @return instructions
	 */
	protected String formatPatchsetInstructions(TicketModel ticket, Patchset patchset) {
		String canonicalUrl = settings.getString(Keys.web.canonicalUrl, "https://localhost:8443");
		String repositoryUrl = canonicalUrl + Constants.R_PATH + ticket.repository;

		String ticketBranch = Repository.shortenRefName(PatchsetCommand.getTicketBranch(ticket.number));
		String patchsetBranch  = PatchsetCommand.getPatchsetBranch(ticket.number, patchset.number);
		String reviewBranch = PatchsetCommand.getReviewBranch(ticket.number);

		String instructions = readResource("commands.md");
		instructions = instructions.replace("${ticketId}", "" + ticket.number);
		instructions = instructions.replace("${patchset}", "" + patchset.number);
		instructions = instructions.replace("${repositoryUrl}", repositoryUrl);
		instructions = instructions.replace("${ticketRef}", ticketBranch);
		instructions = instructions.replace("${patchsetRef}", patchsetBranch);
		instructions = instructions.replace("${reviewBranch}", reviewBranch);
		instructions = instructions.replace("${ticketBranch}", ticketBranch);

		return instructions;
	}

	/**
	 * Gets the usermodel for the username.  Creates a temp model, if required.
	 *
	 * @param username
	 * @return a usermodel
	 */
	protected UserModel getUserModel(String username) {
		UserModel user = userManager.getUserModel(username);
		if (user == null) {
			// create a temporary user model (for unit tests)
			user = new UserModel(username);
		}
		return user;
	}

	/**
	 * Set the proper recipients for a ticket.
	 *
	 * @param ticket
	 * @param mailing
	 */
	protected void setRecipients(TicketModel ticket, Mailing mailing) {
		RepositoryModel repository = repositoryManager.getRepositoryModel(ticket.repository);

		//
		// Direct TO recipients
		// reporter & responsible
		//
		Set<String> tos = new TreeSet<String>();
		tos.add(ticket.createdBy);
		if (!StringUtils.isEmpty(ticket.responsible)) {
			tos.add(ticket.responsible);
		}

		Set<String> toAddresses = new TreeSet<String>();
		for (String name : tos) {
			UserModel user = userManager.getUserModel(name);
			if (user != null && !user.disabled) {
				if (!StringUtils.isEmpty(user.emailAddress)) {
					if (user.canView(repository)) {
						toAddresses.add(user.emailAddress);
					} else {
						LoggerFactory.getLogger(getClass()).warn(
								MessageFormat.format("ticket {0}-{1,number,0}: {2} can not receive notification",
										repository.name, ticket.number, user.username));
					}
				}
			}
		}

		//
		// CC recipients
		//
		Set<String> ccs = new TreeSet<String>();

		// cc users mentioned in last comment
		Change lastChange = ticket.changes.get(ticket.changes.size() - 1);
		if (lastChange.hasComment()) {
			Pattern p = Pattern.compile("\\s@([A-Za-z0-9-_]+)");
			Matcher m = p.matcher(lastChange.comment.text);
			while (m.find()) {
				String username = m.group();
				ccs.add(username);
			}
		}

		// cc users who are watching the ticket
		ccs.addAll(ticket.getWatchers());

		// TODO cc users who are watching the repository

		Set<String> ccAddresses = new TreeSet<String>();

		for (String name : ccs) {
			UserModel user = userManager.getUserModel(name);
			if (user != null && !user.disabled) {
				if (!StringUtils.isEmpty(user.emailAddress)) {
					if (user.canView(repository)) {
						ccAddresses.add(user.emailAddress);
					} else {
						LoggerFactory.getLogger(getClass()).warn(
								MessageFormat.format("ticket {0}-{1,number,0}: {2} can not receive notification",
										repository.name, ticket.number, user.username));
					}
				}
			}
		}

		// repository owners
		for (Owner owner : userManager.getOwners(repository)) {
			if (owner instanceof UserModel) {
				UserModel user = (UserModel) owner;
				if (!StringUtils.isEmpty(user.emailAddress)) {
					ccAddresses.add(user.emailAddress);
				}
			}
		}

		// cc repository mailing list addresses
		if (!ArrayUtils.isEmpty(repository.mailingLists)) {
			ccAddresses.addAll(repository.mailingLists);
		}
		ccAddresses.addAll(settings.getStrings(Keys.mail.mailingLists));

		// respect the author's email preference
		UserModel lastAuthor = userManager.getUserModel(lastChange.author);
		if (!lastAuthor.getPreferences().isEmailMeOnMyTicketChanges()) {
			toAddresses.remove(lastAuthor.emailAddress);
			ccAddresses.remove(lastAuthor.emailAddress);
		}

		mailing.setRecipients(toAddresses);
		mailing.setCCs(ccAddresses);
	}

	protected String readStyle() {
		StringBuilder sb = new StringBuilder();
		sb.append("<style>\n");
		sb.append(readResource("email.css"));
		sb.append("</style>\n");
		return sb.toString();
	}

	protected String readResource(String resource) {
		StringBuilder sb = new StringBuilder();
		InputStream is = null;
		try {
			is = getClass().getResourceAsStream(resource);
			List<String> lines = IOUtils.readLines(is);
			for (String line : lines) {
				sb.append(line).append('\n');
			}
		} catch (IOException e) {

		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
				}
			}
		}
		return sb.toString();
	}
}
