/*
 * Copyright 2011 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.wicket.pages;

import java.awt.Color;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import org.apache.wicket.Component;
import org.apache.wicket.PageParameters;
import org.apache.wicket.behavior.SimpleAttributeModifier;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.data.DataView;
import org.apache.wicket.markup.repeater.data.ListDataProvider;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.revwalk.RevCommit;

import com.gitblit.Keys;
import com.gitblit.models.AnnotatedLine;
import com.gitblit.models.PathModel;
import com.gitblit.utils.ColorFactory;
import com.gitblit.utils.DiffUtils;
import com.gitblit.utils.JGitUtils;
import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.CacheControl;
import com.gitblit.wicket.CacheControl.LastModified;
import com.gitblit.wicket.WicketUtils;
import com.gitblit.wicket.panels.CommitHeaderPanel;
import com.gitblit.wicket.panels.LinkPanel;
import com.gitblit.wicket.panels.PathBreadcrumbsPanel;

@CacheControl(LastModified.BOOT)
public class BlamePage extends RepositoryPage {

	/**
	 * The different types of Blame visualizations.
	 */
	private enum BlameType {
		COMMIT,

		AUTHOR,

		AGE;

		private BlameType() {
		}

		public static BlameType get(String name) {
			for (BlameType blameType : BlameType.values()) {
				if (blameType.name().equalsIgnoreCase(name)) {
					return blameType;
				}
			}
			throw new IllegalArgumentException("Unknown Blame Type [" + name
					+ "]");
		}

		@Override
		public String toString() {
			return name().toLowerCase();
		}
	}

	public BlamePage(PageParameters params) {
		super(params);

		final String blobPath = WicketUtils.getPath(params);

		final String blameTypeParam = params.getString("blametype", BlameType.COMMIT.toString());
		final BlameType activeBlameType = BlameType.get(blameTypeParam);

		RevCommit commit = getCommit();

		add(new BookmarkablePageLink<Void>("blobLink", BlobPage.class,
				WicketUtils.newPathParameter(repositoryName, objectId, blobPath)));
		add(new BookmarkablePageLink<Void>("commitLink", CommitPage.class,
				WicketUtils.newObjectParameter(repositoryName, objectId)));
		add(new BookmarkablePageLink<Void>("commitDiffLink", CommitDiffPage.class,
				WicketUtils.newObjectParameter(repositoryName, objectId)));

		// blame page links
		add(new BookmarkablePageLink<Void>("historyLink", HistoryPage.class,
				WicketUtils.newPathParameter(repositoryName, objectId, blobPath)));

		// "Blame by" links
		for (BlameType type : BlameType.values()) {
			String typeString = type.toString();
			PageParameters blameTypePageParam =
					WicketUtils.newBlameTypeParameter(repositoryName, commit.getName(),
							WicketUtils.getPath(params), typeString);

			String blameByLinkText = "blameBy"
					+ Character.toUpperCase(typeString.charAt(0)) + typeString.substring(1)
					+ "Link";
			BookmarkablePageLink<Void> blameByPageLink =
					new BookmarkablePageLink<Void>(blameByLinkText, BlamePage.class, blameTypePageParam);

			if (activeBlameType == type) {
				blameByPageLink.add(new SimpleAttributeModifier("style", "font-weight:bold;"));
			}

			add(blameByPageLink);
		}

		add(new CommitHeaderPanel("commitHeader", repositoryName, commit));

		add(new PathBreadcrumbsPanel("breadcrumbs", repositoryName, blobPath, objectId));

		String format = app().settings().getString(Keys.web.datetimestampLongFormat,
				"EEEE, MMMM d, yyyy HH:mm Z");
		final DateFormat df = new SimpleDateFormat(format);
		df.setTimeZone(getTimeZone());

		PathModel pathModel = null;
		List<PathModel> paths = JGitUtils.getFilesInPath(getRepository(), StringUtils.getRootPath(blobPath), commit);
		for (PathModel path : paths) {
			if (path.path.equals(blobPath)) {
				pathModel = path;
				break;
			}
		}

		if (pathModel == null) {
			final String notFound = MessageFormat.format("Blame page failed to find {0} in {1} @ {2}",
					blobPath, repositoryName, objectId);
			logger.error(notFound);
			add(new Label("annotation").setVisible(false));
			add(new Label("missingBlob", missingBlob(blobPath, commit)).setEscapeModelStrings(false));
			return;
		}

		add(new Label("missingBlob").setVisible(false));

		List<AnnotatedLine> lines = DiffUtils.blame(getRepository(), blobPath, objectId);
		final Map<?, String> colorMap = initializeColors(activeBlameType, lines);
		ListDataProvider<AnnotatedLine> blameDp = new ListDataProvider<AnnotatedLine>(lines);
		DataView<AnnotatedLine> blameView = new DataView<AnnotatedLine>("annotation", blameDp) {
			private static final long serialVersionUID = 1L;
			private String lastCommitId = "";
			private boolean showInitials = true;
			private String zeroId = ObjectId.zeroId().getName();

			@Override
			public void populateItem(final Item<AnnotatedLine> item) {
				final AnnotatedLine entry = item.getModelObject();

				// commit id and author
				if (!lastCommitId.equals(entry.commitId)) {
					lastCommitId = entry.commitId;
					if (zeroId.equals(entry.commitId)) {
						// unknown commit
						item.add(new Label("commit", "<?>"));
						showInitials = false;
					} else {
						// show the link for first line
						LinkPanel commitLink = new LinkPanel("commit", null,
								getShortObjectId(entry.commitId), CommitPage.class,
								newCommitParameter(entry.commitId));
						WicketUtils.setHtmlTooltip(commitLink,
								MessageFormat.format("{0}, {1}", entry.author, df.format(entry.when)));
						item.add(commitLink);
						WicketUtils.setCssStyle(item, "border-top: 1px solid #ddd;");
						showInitials = true;
					}
				} else {
					if (showInitials) {
						showInitials = false;
						// show author initials
						item.add(new Label("commit", getInitials(entry.author)));
					} else {
						// hide the commit link until the next block
						item.add(new Label("commit").setVisible(false));
					}
				}

				// line number
				item.add(new Label("line", "" + entry.lineNumber));

				// line content
				String color;
				switch (activeBlameType) {
				case AGE:
					color = colorMap.get(entry.when);
					break;
				case AUTHOR:
					color = colorMap.get(entry.author);
					break;
				default:
					color = colorMap.get(entry.commitId);
					break;
				}
				Component data = new Label("data", StringUtils.escapeForHtml(entry.data, true)).setEscapeModelStrings(false);
				data.add(new SimpleAttributeModifier("style", "background-color: " + color + ";"));
				item.add(data);
			}
		};
		add(blameView);
	}

	private String getInitials(String author) {
		StringBuilder sb = new StringBuilder();
		String[] chunks = author.split(" ");
		for (String chunk : chunks) {
			sb.append(chunk.charAt(0));
		}
		return sb.toString().toUpperCase();
	}

	@Override
	protected String getPageName() {
		return getString("gb.blame");
	}

	@Override
	protected boolean isCommitPage() {
		return true;
	}

	@Override
	protected Class<? extends BasePage> getRepoNavPageClass() {
		return TreePage.class;
	}

	protected String missingBlob(String blobPath, RevCommit commit) {
		StringBuilder sb = new StringBuilder();
		sb.append("<div class=\"alert alert-error\">");
		String pattern = getString("gb.doesNotExistInTree").replace("{0}", "<b>{0}</b>").replace("{1}", "<b>{1}</b>");
		sb.append(MessageFormat.format(pattern, blobPath, commit.getTree().getId().getName()));
		sb.append("</div>");
		return sb.toString();
	}

	private Map<?, String> initializeColors(BlameType blameType, List<AnnotatedLine> lines) {
		ColorFactory colorFactory = new ColorFactory();
		Map<?, String> colorMap;

		if (BlameType.AGE == blameType) {
			Set<Date> keys = new TreeSet<Date>(new Comparator<Date>() {
				@Override
				public int compare(Date o1, Date o2) {
					// younger code has a brighter, older code lightens to white
					return o1.compareTo(o2);
				}
			});

			for (AnnotatedLine line : lines) {
				keys.add(line.when);
			}

			// TODO consider making this a setting
			colorMap = colorFactory.getGraduatedColorMap(keys, Color.decode("#FFA63A"));
		} else {
			Set<String> keys = new HashSet<String>();

			for (AnnotatedLine line : lines) {
				if (blameType == BlameType.AUTHOR) {
					keys.add(line.author);
				} else {
					keys.add(line.commitId);
				}
			}

			colorMap = colorFactory.getRandomColorMap(keys);
		}

		return colorMap;
	}
}
