/*
 * 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.wicket.pages;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;

import org.apache.wicket.PageParameters;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.html.link.ExternalLink;
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.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.protocol.http.RequestUtils;
import org.apache.wicket.request.target.basic.RedirectRequestTarget;
import org.eclipse.jgit.diff.DiffEntry.ChangeType;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;

import com.gitblit.models.PathModel.PathChangeModel;
import com.gitblit.models.RefModel;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.SubmoduleModel;
import com.gitblit.servlet.RawServlet;
import com.gitblit.utils.DiffUtils;
import com.gitblit.utils.DiffUtils.DiffOutput;
import com.gitblit.utils.DiffUtils.DiffOutputType;
import com.gitblit.utils.JGitUtils;
import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.SessionlessForm;
import com.gitblit.wicket.WicketUtils;
import com.gitblit.wicket.panels.CommitLegendPanel;
import com.gitblit.wicket.panels.DiffStatPanel;
import com.gitblit.wicket.panels.LinkPanel;
import com.gitblit.wicket.panels.LogPanel;

/**
 * The compare page allows you to compare two branches, tags, or hash ids.
 *
 * @author James Moger
 *
 */
public class ComparePage extends RepositoryPage {

	IModel<String> fromCommitId = new Model<String>("");
	IModel<String> toCommitId = new Model<String>("");

	IModel<String> fromRefId = new Model<String>("");
	IModel<String> toRefId = new Model<String>("");

	public ComparePage(PageParameters params) {
		super(params);
		Repository r = getRepository();
		RepositoryModel repository = getRepositoryModel();

		if (StringUtils.isEmpty(objectId)) {
			// seleciton form
			add(new Label("comparison").setVisible(false));
		} else {
			// active comparison
			Fragment comparison = new Fragment("comparison", "comparisonFragment", this);
			add(comparison);

			RevCommit fromCommit;
			RevCommit toCommit;

			String[] parts = objectId.split("\\.\\.");
			if (parts[0].startsWith("refs/") && parts[1].startsWith("refs/")) {
				// set the ref models
				fromRefId.setObject(parts[0]);
				toRefId.setObject(parts[1]);

				fromCommit = getCommit(r, fromRefId.getObject());
				toCommit = getCommit(r, toRefId.getObject());
			} else {
				// set the id models
				fromCommitId.setObject(parts[0]);
				toCommitId.setObject(parts[1]);

				fromCommit = getCommit(r, fromCommitId.getObject());
				toCommit = getCommit(r, toCommitId.getObject());
			}

			// prepare submodules
			getSubmodules(toCommit);

			final String startId = fromCommit.getId().getName();
			final String endId = toCommit.getId().getName();

			// commit ids
			fromCommitId.setObject(startId);
			toCommitId.setObject(endId);

			final DiffOutput diff = DiffUtils.getDiff(r, fromCommit, toCommit, DiffOutputType.HTML);

			// add compare diffstat
			int insertions = 0;
			int deletions = 0;
			for (PathChangeModel pcm : diff.stat.paths) {
				insertions += pcm.insertions;
				deletions += pcm.deletions;
			}
			comparison.add(new DiffStatPanel("diffStat", insertions, deletions));

			// compare page links
//			comparison.add(new BookmarkablePageLink<Void>("patchLink", PatchPage.class,
//					WicketUtils.newRangeParameter(repositoryName, fromCommitId.toString(), toCommitId.getObject())));

			// display list of commits
			comparison.add(new LogPanel("commitList", repositoryName, objectId, r, 0, 0, repository.showRemoteBranches));

			// changed paths list
			comparison.add(new CommitLegendPanel("commitLegend", diff.stat.paths));
			ListDataProvider<PathChangeModel> pathsDp = new ListDataProvider<PathChangeModel>(diff.stat.paths);
			DataView<PathChangeModel> pathsView = new DataView<PathChangeModel>("changedPath", pathsDp) {
				private static final long serialVersionUID = 1L;
				int counter;

				@Override
				public void populateItem(final Item<PathChangeModel> item) {
					final PathChangeModel entry = item.getModelObject();
					Label changeType = new Label("changeType", "");
					WicketUtils.setChangeTypeCssClass(changeType, entry.changeType);
					setChangeTypeTooltip(changeType, entry.changeType);
					item.add(changeType);
					item.add(new DiffStatPanel("diffStat", entry.insertions, entry.deletions, true));

					boolean hasSubmodule = false;
					String submodulePath = null;
					if (entry.isTree()) {
						// tree
						item.add(new LinkPanel("pathName", null, entry.path, TreePage.class,
								WicketUtils
								.newPathParameter(repositoryName, endId, entry.path)));
					} else if (entry.isSubmodule()) {
						// submodule
						String submoduleId = entry.objectId;
						SubmoduleModel submodule = getSubmodule(entry.path);
						submodulePath = submodule.gitblitPath;
						hasSubmodule = submodule.hasSubmodule;

						// add relative link
						item.add(new LinkPanel("pathName", "list", entry.path + " @ " + getShortObjectId(submoduleId), "#" + entry.path));
					} else {
						// add relative link
						item.add(new LinkPanel("pathName", "list", entry.path, "#" + entry.path));
					}

					// quick links
					if (entry.isSubmodule()) {
						// submodule
						item.add(new ExternalLink("patch", "").setEnabled(false));
						item.add(new BookmarkablePageLink<Void>("view", CommitPage.class, WicketUtils
								.newObjectParameter(submodulePath, entry.objectId)).setEnabled(hasSubmodule));
						item.add(new ExternalLink("raw", "").setEnabled(false));
						item.add(new ExternalLink("blame", "").setEnabled(false));
						item.add(new BookmarkablePageLink<Void>("history", HistoryPage.class, WicketUtils
								.newPathParameter(repositoryName, endId, entry.path))
								.setEnabled(!entry.changeType.equals(ChangeType.ADD)));
					} else {
						// tree or blob
						item.add(new BookmarkablePageLink<Void>("patch", PatchPage.class, WicketUtils
								.newBlobDiffParameter(repositoryName, startId, endId, entry.path))
								.setEnabled(!entry.changeType.equals(ChangeType.DELETE)));
						item.add(new BookmarkablePageLink<Void>("view", BlobPage.class, WicketUtils
								.newPathParameter(repositoryName, endId, entry.path))
								.setEnabled(!entry.changeType.equals(ChangeType.DELETE)));
						String rawUrl = RawServlet.asLink(getContextUrl(), repositoryName, endId, entry.path);
						item.add(new ExternalLink("raw", rawUrl)
								.setEnabled(!entry.changeType.equals(ChangeType.DELETE)));
						item.add(new BookmarkablePageLink<Void>("blame", BlamePage.class, WicketUtils
								.newPathParameter(repositoryName, endId, entry.path))
								.setEnabled(!entry.changeType.equals(ChangeType.ADD)
										&& !entry.changeType.equals(ChangeType.DELETE)));
						item.add(new BookmarkablePageLink<Void>("history", HistoryPage.class, WicketUtils
								.newPathParameter(repositoryName, endId, entry.path))
								.setEnabled(!entry.changeType.equals(ChangeType.ADD)));
					}
					WicketUtils.setAlternatingBackground(item, counter);
					counter++;
				}
			};
			comparison.add(pathsView);
			comparison.add(new Label("diffText", diff.content).setEscapeModelStrings(false));
		}

		//
		// ref selection form
		//
		SessionlessForm<Void> refsForm = new SessionlessForm<Void>("compareRefsForm", getClass(), getPageParameters()) {

			private static final long serialVersionUID = 1L;

			@Override
			public void onSubmit() {
				String from = ComparePage.this.fromRefId.getObject();
				String to = ComparePage.this.toRefId.getObject();

				PageParameters params = WicketUtils.newRangeParameter(repositoryName, from, to);
				String relativeUrl = urlFor(ComparePage.class, params).toString();
				String absoluteUrl = RequestUtils.toAbsolutePath(relativeUrl);
				getRequestCycle().setRequestTarget(new RedirectRequestTarget(absoluteUrl));
			}
		};

		List<String> refs = new ArrayList<String>();
		for (RefModel ref : JGitUtils.getLocalBranches(r, true, -1)) {
			refs.add(ref.getName());
		}
		if (repository.showRemoteBranches) {
			for (RefModel ref : JGitUtils.getRemoteBranches(r, true, -1)) {
				refs.add(ref.getName());
			}
		}
		for (RefModel ref : JGitUtils.getTags(r, true, -1)) {
			refs.add(ref.getName());
		}
		refsForm.add(new DropDownChoice<String>("fromRef", fromRefId, refs).setEnabled(refs.size() > 0));
		refsForm.add(new DropDownChoice<String>("toRef", toRefId, refs).setEnabled(refs.size() > 0));
		add(refsForm);

		//
		// manual ids form
		//
		SessionlessForm<Void> idsForm = new SessionlessForm<Void>("compareIdsForm", getClass(), getPageParameters()) {

			private static final long serialVersionUID = 1L;

			@Override
			public void onSubmit() {
				String from = ComparePage.this.fromCommitId.getObject();
				String to = ComparePage.this.toCommitId.getObject();

				PageParameters params = WicketUtils.newRangeParameter(repositoryName, from, to);
				String relativeUrl = urlFor(ComparePage.class, params).toString();
				String absoluteUrl = RequestUtils.toAbsolutePath(relativeUrl);
				getRequestCycle().setRequestTarget(new RedirectRequestTarget(absoluteUrl));
			}
		};

		TextField<String> fromIdField = new TextField<String>("fromId", fromCommitId);
		WicketUtils.setInputPlaceholder(fromIdField, getString("gb.from") + "...");
		idsForm.add(fromIdField);

		TextField<String> toIdField = new TextField<String>("toId", toCommitId);
		WicketUtils.setInputPlaceholder(toIdField, getString("gb.to") + "...");
		idsForm.add(toIdField);
		add(idsForm);

		r.close();
	}

	@Override
	protected String getPageName() {
		return getString("gb.compare");
	}

	@Override
	protected Class<? extends BasePage> getRepoNavPageClass() {
		return ComparePage.class;
	}

	private RevCommit getCommit(Repository r, String rev)
	{
		RevCommit otherCommit = JGitUtils.getCommit(r, rev);
		if (otherCommit == null) {
			error(MessageFormat.format(getString("gb.failedToFindCommit"), rev, repositoryName, getPageName()), true);
		}
		return otherCommit;
	}
}
