/*
 * 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.panels;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.html.panel.Fragment;
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.apache.wicket.model.StringResourceModel;
import org.eclipse.jgit.diff.DiffEntry.ChangeType;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.PathFilterGroup;

import com.gitblit.Constants;
import com.gitblit.Keys;
import com.gitblit.models.PathModel;
import com.gitblit.models.PathModel.PathChangeModel;
import com.gitblit.models.RefModel;
import com.gitblit.models.SubmoduleModel;
import com.gitblit.utils.JGitUtils;
import com.gitblit.utils.MarkdownUtils;
import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.WicketUtils;
import com.gitblit.wicket.pages.BlobDiffPage;
import com.gitblit.wicket.pages.BlobPage;
import com.gitblit.wicket.pages.CommitDiffPage;
import com.gitblit.wicket.pages.CommitPage;
import com.gitblit.wicket.pages.GitSearchPage;
import com.gitblit.wicket.pages.HistoryPage;
import com.gitblit.wicket.pages.TreePage;

public class HistoryPanel extends BasePanel {

	private static final long serialVersionUID = 1L;

	private boolean hasMore;

	public HistoryPanel(String wicketId, final String repositoryName, final String objectId,
			final String path, Repository r, int limit, int pageOffset, boolean showRemoteRefs) {
		super(wicketId);
		boolean pageResults = limit <= 0;
		int itemsPerPage = app().settings().getInteger(Keys.web.itemsPerPage, 50);
		if (itemsPerPage <= 1) {
			itemsPerPage = 50;
		}

		RevCommit commit = JGitUtils.getCommit(r, objectId);
		PathModel matchingPath = null;
		Map<String, SubmoduleModel> submodules = new HashMap<String, SubmoduleModel>();

		if (commit == null) {
			// commit missing
			String msg = MessageFormat.format("Failed to find history of **{0}** *{1}*",
					path, objectId);
			logger().error(msg + " " + repositoryName);
			add(new Label("commitHeader", MarkdownUtils.transformMarkdown(msg)).setEscapeModelStrings(false));
			add(new Label("breadcrumbs"));
		} else {
			// commit found
			List<PathChangeModel> paths = JGitUtils.getFilesInCommit(r, commit);
			add(new CommitHeaderPanel("commitHeader", repositoryName, commit));
			add(new PathBreadcrumbsPanel("breadcrumbs", repositoryName, path, objectId));
			for (SubmoduleModel model : JGitUtils.getSubmodules(r, commit.getTree())) {
				submodules.put(model.path, model);
			}

			for (PathModel p : paths) {
				if (p.path.equals(path)) {
					matchingPath = p;
					break;
				}
			}
			if (matchingPath == null) {
				// path not in commit
				// manually locate path in tree
				TreeWalk tw = new TreeWalk(r);
				tw.reset();
				tw.setRecursive(true);
				try {
					tw.addTree(commit.getTree());
					tw.setFilter(PathFilterGroup.createFromStrings(Collections.singleton(path)));
					while (tw.next()) {
						if (tw.getPathString().equals(path)) {
							matchingPath = new PathChangeModel(tw.getPathString(), tw.getPathString(), 0, tw
								.getRawMode(0), tw.getObjectId(0).getName(), commit.getId().getName(),
								ChangeType.MODIFY);
						}
					}
				} catch (Exception e) {
				} finally {
					tw.release();
				}
			}
		}

		final boolean isTree = matchingPath == null ? true : matchingPath.isTree();
		final boolean isSubmodule = matchingPath == null ? false : matchingPath.isSubmodule();

		// submodule
		final String submodulePath;
		final boolean hasSubmodule;
		if (isSubmodule) {
			SubmoduleModel submodule = getSubmodule(submodules, repositoryName, matchingPath == null ? null : matchingPath.path);
			submodulePath = submodule.gitblitPath;
			hasSubmodule = submodule.hasSubmodule;
		} else {
			submodulePath = "";
			hasSubmodule = false;
		}

		final Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(r, showRemoteRefs);
		List<RevCommit> commits;
		if (pageResults) {
			// Paging result set
			commits = JGitUtils.getRevLog(r, objectId, path, pageOffset * itemsPerPage,
					itemsPerPage);
		} else {
			// Fixed size result set
			commits = JGitUtils.getRevLog(r, objectId, path, 0, limit);
		}

		// inaccurate way to determine if there are more commits.
		// works unless commits.size() represents the exact end.
		hasMore = commits.size() >= itemsPerPage;

		final int hashLen = app().settings().getInteger(Keys.web.shortCommitIdLength, 6);
		ListDataProvider<RevCommit> dp = new ListDataProvider<RevCommit>(commits);
		DataView<RevCommit> logView = new DataView<RevCommit>("commit", dp) {
			private static final long serialVersionUID = 1L;
			int counter;

			@Override
			public void populateItem(final Item<RevCommit> item) {
				final RevCommit entry = item.getModelObject();
				final Date date = JGitUtils.getCommitDate(entry);

				item.add(WicketUtils.createDateLabel("commitDate", date, getTimeZone(), getTimeUtils()));

				// author search link
				String author = entry.getAuthorIdent().getName();
				LinkPanel authorLink = new LinkPanel("commitAuthor", "list", author,
						GitSearchPage.class,
						WicketUtils.newSearchParameter(repositoryName, null,
								author, Constants.SearchType.AUTHOR));
				setPersonSearchTooltip(authorLink, author, Constants.SearchType.AUTHOR);
				item.add(authorLink);

				// merge icon
				if (entry.getParentCount() > 1) {
					item.add(WicketUtils.newImage("commitIcon", "commit_merge_16x16.png"));
				} else {
					item.add(WicketUtils.newBlankImage("commitIcon"));
				}

				String shortMessage = entry.getShortMessage();
				String trimmedMessage = shortMessage;
				if (allRefs.containsKey(entry.getId())) {
					trimmedMessage = StringUtils.trimString(shortMessage, Constants.LEN_SHORTLOG_REFS);
				} else {
					trimmedMessage = StringUtils.trimString(shortMessage, Constants.LEN_SHORTLOG);
				}
				LinkPanel shortlog = new LinkPanel("commitShortMessage", "list subject",
						trimmedMessage, CommitPage.class, WicketUtils.newObjectParameter(
								repositoryName, entry.getName()));
				if (!shortMessage.equals(trimmedMessage)) {
					WicketUtils.setHtmlTooltip(shortlog, shortMessage);
				}
				item.add(shortlog);

				item.add(new RefsPanel("commitRefs", repositoryName, entry, allRefs));

				if (isTree) {
					// tree
					item.add(new Label("hashLabel", getString("gb.tree") + "@"));
					LinkPanel commitHash = new LinkPanel("hashLink", null, entry.getName().substring(0, hashLen),
							TreePage.class, WicketUtils.newObjectParameter(
									repositoryName, entry.getName()));
					WicketUtils.setCssClass(commitHash, "shortsha1");
					WicketUtils.setHtmlTooltip(commitHash, entry.getName());
					item.add(commitHash);

					Fragment links = new Fragment("historyLinks", "treeLinks", this);
					links.add(new BookmarkablePageLink<Void>("commitdiff", CommitDiffPage.class,
							WicketUtils.newObjectParameter(repositoryName, entry.getName())));
					item.add(links);
				} else if (isSubmodule) {
					// submodule
					Repository repository = app().repositories().getRepository(repositoryName);
					String submoduleId = JGitUtils.getSubmoduleCommitId(repository, path, entry);
					repository.close();
					if (StringUtils.isEmpty(submoduleId)) {
						// not a submodule at this commit, just a matching path
						item.add(new Label("hashLabel").setVisible(false));
						item.add(new Label("hashLink").setVisible(false));
					} else {
						// really a submodule
						item.add(new Label("hashLabel", submodulePath + "@"));
						LinkPanel commitHash = new LinkPanel("hashLink", null, submoduleId.substring(0, hashLen),
								TreePage.class, WicketUtils.newObjectParameter(
										submodulePath, submoduleId));
						WicketUtils.setCssClass(commitHash, "shortsha1");
						WicketUtils.setHtmlTooltip(commitHash, submoduleId);
						item.add(commitHash.setEnabled(hasSubmodule));
					}
					Fragment links = new Fragment("historyLinks", "treeLinks", this);
					links.add(new BookmarkablePageLink<Void>("commitdiff", CommitDiffPage.class,
							WicketUtils.newObjectParameter(repositoryName, entry.getName())));
					item.add(links);
				} else {
					// commit
					item.add(new Label("hashLabel", getString("gb.blob") + "@"));
					LinkPanel commitHash = new LinkPanel("hashLink", null, entry.getName().substring(0, hashLen),
							BlobPage.class, WicketUtils.newPathParameter(
									repositoryName, entry.getName(), path));
					WicketUtils.setCssClass(commitHash, "sha1");
					WicketUtils.setHtmlTooltip(commitHash, entry.getName());
					item.add(commitHash);

					Fragment links = new Fragment("historyLinks", "blobLinks", this);
					links.add(new BookmarkablePageLink<Void>("commitdiff", CommitDiffPage.class,
							WicketUtils.newObjectParameter(repositoryName, entry.getName())));
					links.add(new BookmarkablePageLink<Void>("difftocurrent", BlobDiffPage.class,
							WicketUtils.newBlobDiffParameter(repositoryName, entry.getName(),
									objectId, path)).setEnabled(counter > 0));
					item.add(links);
				}

				WicketUtils.setAlternatingBackground(item, counter);
				counter++;
			}
		};
		add(logView);

		// determine to show pager, more, or neither
		if (limit <= 0) {
			// no display limit
			add(new Label("moreHistory", "").setVisible(false));
		} else {
			if (pageResults) {
				// paging
				add(new Label("moreHistory", "").setVisible(false));
			} else {
				// more
				if (commits.size() == limit) {
					// show more
					add(new LinkPanel("moreHistory", "link", new StringResourceModel(
							"gb.moreHistory", this, null), HistoryPage.class,
							WicketUtils.newPathParameter(repositoryName, objectId, path)));
				} else {
					// no more
					add(new Label("moreHistory", "").setVisible(false));
				}
			}
		}
	}

	public boolean hasMore() {
		return hasMore;
	}

	protected SubmoduleModel getSubmodule(Map<String, SubmoduleModel> submodules, String repositoryName, String path) {
		SubmoduleModel model = submodules.get(path);
		if (model == null) {
			// undefined submodule?!
			model = new SubmoduleModel(path.substring(path.lastIndexOf('/') + 1), path, path);
			model.hasSubmodule = false;
			model.gitblitPath = model.name;
			return model;
		} else {
			// extract the repository name from the clone url
			List<String> patterns = app().settings().getStrings(Keys.git.submoduleUrlPatterns);
			String submoduleName = StringUtils.extractRepositoryPath(model.url, patterns.toArray(new String[0]));

			// determine the current path for constructing paths relative
			// to the current repository
			String currentPath = "";
			if (repositoryName.indexOf('/') > -1) {
				currentPath = repositoryName.substring(0, repositoryName.lastIndexOf('/') + 1);
			}

			// try to locate the submodule repository
			// prefer bare to non-bare names
			List<String> candidates = new ArrayList<String>();

			// relative
			candidates.add(currentPath + StringUtils.stripDotGit(submoduleName));
			candidates.add(candidates.get(candidates.size() - 1) + ".git");

			// relative, no subfolder
			if (submoduleName.lastIndexOf('/') > -1) {
				String name = submoduleName.substring(submoduleName.lastIndexOf('/') + 1);
				candidates.add(currentPath + StringUtils.stripDotGit(name));
				candidates.add(candidates.get(candidates.size() - 1) + ".git");
			}

			// absolute
			candidates.add(StringUtils.stripDotGit(submoduleName));
			candidates.add(candidates.get(candidates.size() - 1) + ".git");

			// absolute, no subfolder
			if (submoduleName.lastIndexOf('/') > -1) {
				String name = submoduleName.substring(submoduleName.lastIndexOf('/') + 1);
				candidates.add(StringUtils.stripDotGit(name));
				candidates.add(candidates.get(candidates.size() - 1) + ".git");
			}

			// create a unique, ordered set of candidate paths
			Set<String> paths = new LinkedHashSet<String>(candidates);
			for (String candidate : paths) {
				if (app().repositories().hasRepository(candidate)) {
					model.hasSubmodule = true;
					model.gitblitPath = candidate;
					return model;
				}
			}

			// we do not have a copy of the submodule, but we need a path
			model.gitblitPath = candidates.get(0);
			return model;
		}
	}
}
