/*
 * 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.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.wicket.Component;
import org.apache.wicket.PageParameters;
import org.apache.wicket.extensions.markup.html.repeater.data.sort.OrderByBorder;
import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.html.link.Link;
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.IDataProvider;
import org.apache.wicket.markup.repeater.data.ListDataProvider;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;

import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.Keys;
import com.gitblit.models.Owner;
import com.gitblit.models.ProjectModel;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.ModelUtils;
import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.GitBlitWebSession;
import com.gitblit.wicket.WicketUtils;
import com.gitblit.wicket.pages.BasePage;
import com.gitblit.wicket.pages.ProjectPage;
import com.gitblit.wicket.pages.RepositoriesPage;
import com.gitblit.wicket.pages.SummaryPage;
import com.gitblit.wicket.pages.UserPage;

public class RepositoriesPanel extends BasePanel {

	private static final long serialVersionUID = 1L;

	public RepositoriesPanel(String wicketId, final boolean showAdmin, final boolean showManagement,
			List<RepositoryModel> models, boolean enableLinks,
			final Map<AccessRestrictionType, String> accessRestrictionTranslations) {
		super(wicketId);

		final boolean linksActive = enableLinks;
		final boolean showSize = app().settings().getBoolean(Keys.web.showRepositorySizes, true);

		final UserModel user = GitBlitWebSession.get().getUser();

		final IDataProvider<RepositoryModel> dp;

		Fragment managementLinks;
		if (showAdmin) {
			// user is admin
			managementLinks = new Fragment("managementPanel", "adminLinks", this);
			managementLinks.add(new Link<Void>("clearCache") {

				private static final long serialVersionUID = 1L;

				@Override
				public void onClick() {
					app().repositories().resetRepositoryListCache();
					setResponsePage(RepositoriesPage.class);
				}
			}.setVisible(app().settings().getBoolean(Keys.git.cacheRepositoryList, true)));
			managementLinks.add(new BookmarkablePageLink<Void>("newRepository", app().getNewRepositoryPage()));
			add(managementLinks);
		} else if (showManagement && user != null && user.canCreate()) {
			// user can create personal repositories
			managementLinks = new Fragment("managementPanel", "personalLinks", this);
			managementLinks.add(new BookmarkablePageLink<Void>("newRepository", app().getNewRepositoryPage()));
			add(managementLinks);
		} else {
			// user has no management permissions
			add (new Label("managementPanel").setVisible(false));
		}

		if (app().settings().getString(Keys.web.repositoryListType, "flat").equalsIgnoreCase("grouped")) {
			List<RepositoryModel> rootRepositories = new ArrayList<RepositoryModel>();
			Map<String, List<RepositoryModel>> groups = new HashMap<String, List<RepositoryModel>>();
			for (RepositoryModel model : models) {
				String rootPath = StringUtils.getRootPath(model.name);
				if (StringUtils.isEmpty(rootPath)) {
					// root repository
					rootRepositories.add(model);
				} else {
					// non-root, grouped repository
					if (!groups.containsKey(rootPath)) {
						groups.put(rootPath, new ArrayList<RepositoryModel>());
					}
					groups.get(rootPath).add(model);
				}
			}
			List<String> roots = new ArrayList<String>(groups.keySet());
			Collections.sort(roots);

			if (rootRepositories.size() > 0) {
				// inject the root repositories at the top of the page
				roots.add(0, "");
				groups.put("", rootRepositories);
			}

			List<RepositoryModel> groupedModels = new ArrayList<RepositoryModel>();
			for (String root : roots) {
				List<RepositoryModel> subModels = groups.get(root);
				ProjectModel project = app().projects().getProjectModel(root);
				GroupRepositoryModel group = new GroupRepositoryModel(project == null ? root : project.name, subModels.size());
				if (project != null) {
					group.title = project.title;
					group.description = project.description;
				}
				groupedModels.add(group);
				Collections.sort(subModels);
				groupedModels.addAll(subModels);
			}
			dp = new ListDataProvider<RepositoryModel>(groupedModels);
		} else {
			dp = new SortableRepositoriesProvider(models);
		}

		final boolean showSwatch = app().settings().getBoolean(Keys.web.repositoryListSwatches, true);

		DataView<RepositoryModel> dataView = new DataView<RepositoryModel>("row", dp) {
			private static final long serialVersionUID = 1L;
			int counter;
			String currGroupName;

			@Override
			protected void onBeforeRender() {
				super.onBeforeRender();
				counter = 0;
			}

			@Override
			public void populateItem(final Item<RepositoryModel> item) {
				final RepositoryModel entry = item.getModelObject();
				if (entry instanceof GroupRepositoryModel) {
					GroupRepositoryModel groupRow = (GroupRepositoryModel) entry;
					currGroupName = entry.name;
					Fragment row = new Fragment("rowContent", "groupRepositoryRow", this);
					item.add(row);

					String name = groupRow.name;
					if (name.startsWith(ModelUtils.getUserRepoPrefix())) {
						// user page
						String username = ModelUtils.getUserNameFromRepoPath(name);
						UserModel user = app().users().getUserModel(username);
						row.add(new LinkPanel("groupName", null, (user == null ? username : user.getDisplayName()) + " (" + groupRow.count + ")", UserPage.class, WicketUtils.newUsernameParameter(username)));
						row.add(new Label("groupDescription", getString("gb.personalRepositories")));
					} else {
						// project page
						row.add(new LinkPanel("groupName", null, groupRow.toString(), ProjectPage.class, WicketUtils.newProjectParameter(entry.name)));
						row.add(new Label("groupDescription", entry.description == null ? "":entry.description));
					}
					WicketUtils.setCssClass(item, "group");
					// reset counter so that first row is light background
					counter = 0;
					return;
				}
				Fragment row = new Fragment("rowContent", "repositoryRow", this);
				item.add(row);

				// try to strip group name for less cluttered list
				String repoName = entry.toString();
				if (!StringUtils.isEmpty(currGroupName) && (repoName.indexOf('/') > -1)) {
					repoName = repoName.substring(currGroupName.length() + 1);
				}

				// repository swatch
				Component swatch;
				if (entry.isBare){
					swatch = new Label("repositorySwatch", "&nbsp;").setEscapeModelStrings(false);
				} else {
					swatch = new Label("repositorySwatch", "!");
					WicketUtils.setHtmlTooltip(swatch, getString("gb.workingCopyWarning"));
				}
				WicketUtils.setCssBackground(swatch, entry.toString());
				row.add(swatch);
				swatch.setVisible(showSwatch);

				if (linksActive) {
					Class<? extends BasePage> linkPage = SummaryPage.class;
					PageParameters pp = WicketUtils.newRepositoryParameter(entry.name);
					row.add(new LinkPanel("repositoryName", "list", repoName, linkPage, pp));
					row.add(new LinkPanel("repositoryDescription", "list", entry.description,
							linkPage, pp));
				} else {
					// no links like on a federation page
					row.add(new Label("repositoryName", repoName));
					row.add(new Label("repositoryDescription", entry.description));
				}
				if (entry.hasCommits) {
					// Existing repository
					row.add(new Label("repositorySize", entry.size).setVisible(showSize));
				} else {
					// New repository
					row.add(new Label("repositorySize", "<span class='empty'>(" + getString("gb.empty") + ")</span>")
							.setEscapeModelStrings(false));
				}

				if (entry.isSparkleshared()) {
					row.add(WicketUtils.newImage("sparkleshareIcon", "star_16x16.png",
							getString("gb.isSparkleshared")));
				} else {
					row.add(WicketUtils.newClearPixel("sparkleshareIcon").setVisible(false));
				}

				if (entry.isMirror) {
					row.add(WicketUtils.newImage("mirrorIcon", "mirror_16x16.png",
							getString("gb.isMirror")));
				} else {
					row.add(WicketUtils.newClearPixel("mirrorIcon").setVisible(false));
				}

				if (entry.isFork()) {
					row.add(WicketUtils.newImage("forkIcon", "commit_divide_16x16.png",
							getString("gb.isFork")));
				} else {
					row.add(WicketUtils.newClearPixel("forkIcon").setVisible(false));
				}

				if (entry.isFrozen) {
					row.add(WicketUtils.newImage("frozenIcon", "cold_16x16.png",
							getString("gb.isFrozen")));
				} else {
					row.add(WicketUtils.newClearPixel("frozenIcon").setVisible(false));
				}

				if (entry.isFederated) {
					row.add(WicketUtils.newImage("federatedIcon", "federated_16x16.png",
							getString("gb.isFederated")));
				} else {
					row.add(WicketUtils.newClearPixel("federatedIcon").setVisible(false));
				}
				switch (entry.accessRestriction) {
				case NONE:
					row.add(WicketUtils.newBlankImage("accessRestrictionIcon"));
					break;
				case PUSH:
					row.add(WicketUtils.newImage("accessRestrictionIcon", "lock_go_16x16.png",
							accessRestrictionTranslations.get(entry.accessRestriction)));
					break;
				case CLONE:
					row.add(WicketUtils.newImage("accessRestrictionIcon", "lock_pull_16x16.png",
							accessRestrictionTranslations.get(entry.accessRestriction)));
					break;
				case VIEW:
					row.add(WicketUtils.newImage("accessRestrictionIcon", "shield_16x16.png",
							accessRestrictionTranslations.get(entry.accessRestriction)));
					break;
				default:
					row.add(WicketUtils.newBlankImage("accessRestrictionIcon"));
				}

				List<Owner> owners = app().users().getOwners(entry);
				// display first owner
				String owner = "";
				if (!owners.isEmpty()) {
					owner = owners.get(0).getDisplayName();
					if (owners.size() > 1) {
						owner += ", ...";
					}
				}
				Label ownerLabel = new Label("repositoryOwner", owner);
				WicketUtils.setHtmlTooltip(ownerLabel, ArrayUtils.toString(owners));
				row.add(ownerLabel);

				String lastChange;
				if (entry.lastChange.getTime() == 0) {
					lastChange = "--";
				} else {
					lastChange = getTimeUtils().timeAgo(entry.lastChange);
				}
				Label lastChangeLabel = new Label("repositoryLastChange", lastChange);
				row.add(lastChangeLabel);
				WicketUtils.setCssClass(lastChangeLabel, getTimeUtils().timeAgoCss(entry.lastChange));
				if (!StringUtils.isEmpty(entry.lastChangeAuthor)) {
					WicketUtils.setHtmlTooltip(lastChangeLabel, getString("gb.author") + ": " + entry.lastChangeAuthor);
				}

				WicketUtils.setAlternatingBackground(item, counter);
				counter++;
			}
		};
		add(dataView);

		if (dp instanceof SortableDataProvider<?>) {
			// add sortable header
			SortableDataProvider<?> sdp = (SortableDataProvider<?>) dp;
			Fragment fragment = new Fragment("headerContent", "flatRepositoryHeader", this);
			fragment.add(newSort("orderByRepository", SortBy.repository, sdp, dataView));
			fragment.add(newSort("orderByDescription", SortBy.description, sdp, dataView));
			fragment.add(newSort("orderByOwner", SortBy.owner, sdp, dataView));
			fragment.add(newSort("orderByDate", SortBy.date, sdp, dataView));
			add(fragment);
		} else {
			// not sortable
			Fragment fragment = new Fragment("headerContent", "groupRepositoryHeader", this);
			add(fragment);
		}
	}

	private static class GroupRepositoryModel extends RepositoryModel {

		private static final long serialVersionUID = 1L;

		int count;
		String title;

		GroupRepositoryModel(String name, int count) {
			super(name, "", new Date(0));
			this.count = count;
		}

		@Override
		public String toString() {
			return (StringUtils.isEmpty(title) ? name  : title) + " (" + count + ")";
		}
	}

	protected enum SortBy {
		repository, description, owner, date;
	}

	protected OrderByBorder newSort(String wicketId, SortBy field, SortableDataProvider<?> dp,
			final DataView<?> dataView) {
		return new OrderByBorder(wicketId, field.name(), dp) {
			private static final long serialVersionUID = 1L;

			@Override
			protected void onSortChanged() {
				dataView.setCurrentPage(0);
			}
		};
	}

	private static class SortableRepositoriesProvider extends SortableDataProvider<RepositoryModel> {

		private static final long serialVersionUID = 1L;

		private List<RepositoryModel> list;

		protected SortableRepositoriesProvider(List<RepositoryModel> list) {
			this.list = list;
			setSort(SortBy.date.name(), false);
		}

		@Override
		public int size() {
			if (list == null) {
				return 0;
			}
			return list.size();
		}

		@Override
		public IModel<RepositoryModel> model(RepositoryModel header) {
			return new Model<RepositoryModel>(header);
		}

		@Override
		public Iterator<RepositoryModel> iterator(int first, int count) {
			SortParam sp = getSort();
			String prop = sp.getProperty();
			final boolean asc = sp.isAscending();

			if (prop == null || prop.equals(SortBy.date.name())) {
				Collections.sort(list, new Comparator<RepositoryModel>() {
					@Override
					public int compare(RepositoryModel o1, RepositoryModel o2) {
						if (asc) {
							return o1.lastChange.compareTo(o2.lastChange);
						}
						return o2.lastChange.compareTo(o1.lastChange);
					}
				});
			} else if (prop.equals(SortBy.repository.name())) {
				Collections.sort(list, new Comparator<RepositoryModel>() {
					@Override
					public int compare(RepositoryModel o1, RepositoryModel o2) {
						if (asc) {
							return o1.name.compareTo(o2.name);
						}
						return o2.name.compareTo(o1.name);
					}
				});
			} else if (prop.equals(SortBy.description.name())) {
				Collections.sort(list, new Comparator<RepositoryModel>() {
					@Override
					public int compare(RepositoryModel o1, RepositoryModel o2) {
						if (asc) {
							return o1.description.compareTo(o2.description);
						}
						return o2.description.compareTo(o1.description);
					}
				});
			}
			return list.subList(first, first + count).iterator();
		}
	}
}
