/*
 * 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.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.wicket.PageParameters;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormChoiceComponentUpdatingBehavior;
import org.apache.wicket.behavior.SimpleAttributeModifier;
import org.apache.wicket.extensions.markup.html.form.palette.Palette;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.CheckBox;
import org.apache.wicket.markup.html.form.ChoiceRenderer;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.IChoiceRenderer;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.model.util.CollectionModel;
import org.apache.wicket.model.util.ListModel;
import org.eclipse.jgit.lib.Repository;

import com.gitblit.Constants;
import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.Constants.AuthorizationControl;
import com.gitblit.Constants.CommitMessageRenderer;
import com.gitblit.Constants.FederationStrategy;
import com.gitblit.Constants.RegistrantType;
import com.gitblit.GitBlitException;
import com.gitblit.Keys;
import com.gitblit.models.Owner;
import com.gitblit.models.RegistrantAccessPermission;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserChoice;
import com.gitblit.models.UserModel;
import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.GitBlitWebSession;
import com.gitblit.wicket.StringChoiceRenderer;
import com.gitblit.wicket.WicketUtils;
import com.gitblit.wicket.panels.AccessPolicyPanel;
import com.gitblit.wicket.panels.BasePanel.JavascriptEventConfirmation;
import com.gitblit.wicket.panels.BooleanOption;
import com.gitblit.wicket.panels.BulletListPanel;
import com.gitblit.wicket.panels.ChoiceOption;
import com.gitblit.wicket.panels.RegistrantPermissionsPanel;
import com.gitblit.wicket.panels.RepositoryNamePanel;
import com.gitblit.wicket.panels.TextOption;

public class EditRepositoryPage extends RootSubPage {

	private final boolean isCreate;

	RepositoryNamePanel namePanel;

	AccessPolicyPanel accessPolicyPanel;

	private boolean isAdmin;

	RepositoryModel repositoryModel;

	private IModel<String> metricAuthorExclusions;

	private IModel<String> mailingLists;

	public EditRepositoryPage() {
		// create constructor
		super();
		isCreate = true;
		RepositoryModel model = new RepositoryModel();
		String restriction = app().settings().getString(Keys.git.defaultAccessRestriction, "PUSH");
		model.accessRestriction = AccessRestrictionType.fromName(restriction);
		String authorization = app().settings().getString(Keys.git.defaultAuthorizationControl, null);
		model.authorizationControl = AuthorizationControl.fromName(authorization);

		GitBlitWebSession session = GitBlitWebSession.get();
		UserModel user = session.getUser();
		if (user != null && user.canCreate() && !user.canAdmin()) {
			// personal create permissions, inject personal repository path
			model.name = user.getPersonalPath();

			// personal repositories are private by default
			model.accessRestriction = AccessRestrictionType.VIEW;
			model.authorizationControl = AuthorizationControl.NAMED;
		}

		setupPage(model);
		setStatelessHint(false);
		setOutputMarkupId(true);
	}

	public EditRepositoryPage(PageParameters params) {
		// edit constructor
		super(params);
		isCreate = false;
		String name = WicketUtils.getRepositoryName(params);
		RepositoryModel model = app().repositories().getRepositoryModel(name);
		setupPage(model);
		setStatelessHint(false);
		setOutputMarkupId(true);
	}

	@Override
	protected boolean requiresPageMap() {
		return true;
	}

	@Override
	protected Class<? extends BasePage> getRootNavPageClass() {
		return RepositoriesPage.class;
	}

	protected void setupPage(RepositoryModel model) {
		this.repositoryModel = model;

		// ensure this user can create or edit this repository
		checkPermissions(repositoryModel);

		List<String> indexedBranches = new ArrayList<String>();
		List<String> federationSets = new ArrayList<String>();
		final List<RegistrantAccessPermission> repositoryUsers = new ArrayList<RegistrantAccessPermission>();
		final List<RegistrantAccessPermission> repositoryTeams = new ArrayList<RegistrantAccessPermission>();
		List<String> preReceiveScripts = new ArrayList<String>();
		List<String> postReceiveScripts = new ArrayList<String>();

		GitBlitWebSession session = GitBlitWebSession.get();
		final UserModel user = session.getUser() == null ? UserModel.ANONYMOUS : session.getUser();

		if (isCreate) {
			if (user.canAdmin()) {
				super.setupPage(getString("gb.newRepository"), "");
			} else {
				super.setupPage(getString("gb.newRepository"), user.getDisplayName());
			}
		} else {
			super.setupPage(getString("gb.edit"), repositoryModel.name);
			repositoryUsers.addAll(app().repositories().getUserAccessPermissions(repositoryModel));
			repositoryTeams.addAll(app().repositories().getTeamAccessPermissions(repositoryModel));
			Collections.sort(repositoryUsers);
			Collections.sort(repositoryTeams);

			federationSets.addAll(repositoryModel.federationSets);
			if (!ArrayUtils.isEmpty(repositoryModel.indexedBranches)) {
				indexedBranches.addAll(repositoryModel.indexedBranches);
			}
		}

		final String oldName = repositoryModel.name;

		final RegistrantPermissionsPanel usersPalette = new RegistrantPermissionsPanel("users",
				RegistrantType.USER, app().users().getAllUsernames(), repositoryUsers, getAccessPermissions());
		final RegistrantPermissionsPanel teamsPalette = new RegistrantPermissionsPanel("teams",
				RegistrantType.TEAM, app().users().getAllTeamNames(), repositoryTeams, getAccessPermissions());

		// owners palette
		List<UserChoice> owners = new ArrayList<UserChoice>();
		for (Owner owner : app().users().getOwners(repositoryModel)) {
			if (owner instanceof UserModel) {
				UserModel userOwner = (UserModel) owner;
				owners.add(new UserChoice(userOwner.getDisplayName(), userOwner.username, userOwner.emailAddress));
			}
		}
		List<UserChoice> persons = new ArrayList<UserChoice>();
		for (String person : app().users().getAllUsernames()) {
			UserModel o = app().users().getUserModel(person);
			if (o != null) {
				persons.add(new UserChoice(o.getDisplayName(), o.username, o.emailAddress));
			} else {
				persons.add(new UserChoice(person));
			}
		}
		final Palette<UserChoice> ownersPalette = new Palette<UserChoice>("owners", new ListModel<UserChoice>(owners), new CollectionModel<UserChoice>(
		      persons), new ChoiceRenderer<UserChoice>(null, "userId"), 12, false);

		// indexed local branches palette
		List<String> allLocalBranches = new ArrayList<String>();
		allLocalBranches.add(Constants.DEFAULT_BRANCH);
		allLocalBranches.addAll(repositoryModel.getLocalBranches());
		boolean luceneEnabled = app().settings().getBoolean(Keys.web.allowLuceneIndexing, true);
		final Palette<String> indexedBranchesPalette = new Palette<String>("indexedBranches", new ListModel<String>(
				indexedBranches), new CollectionModel<String>(allLocalBranches),
				new StringChoiceRenderer(), 8, false);
		indexedBranchesPalette.setEnabled(luceneEnabled);

		// federation sets palette
		List<String> sets = app().settings().getStrings(Keys.federation.sets);
		final Palette<String> federationSetsPalette = new Palette<String>("federationSets",
				new ListModel<String>(federationSets), new CollectionModel<String>(sets),
				new StringChoiceRenderer(), 8, false);

		// pre-receive palette
		if (!ArrayUtils.isEmpty(repositoryModel.preReceiveScripts)) {
			preReceiveScripts.addAll(repositoryModel.preReceiveScripts);
		}
		final Palette<String> preReceivePalette = new Palette<String>("preReceiveScripts",
				new ListModel<String>(preReceiveScripts), new CollectionModel<String>(app().repositories()
						.getPreReceiveScriptsUnused(repositoryModel)),
				new StringChoiceRenderer(), 12, true);

		// post-receive palette
		if (!ArrayUtils.isEmpty(repositoryModel.postReceiveScripts)) {
			postReceiveScripts.addAll(repositoryModel.postReceiveScripts);
		}
		final Palette<String> postReceivePalette = new Palette<String>("postReceiveScripts",
				new ListModel<String>(postReceiveScripts), new CollectionModel<String>(app().repositories()
						.getPostReceiveScriptsUnused(repositoryModel)),
				new StringChoiceRenderer(), 12, true);

		// custom fields
		final Map<String, String> customFieldsMap = app().settings().getMap(Keys.groovy.customFields);
		List<String> customKeys = new ArrayList<String>(customFieldsMap.keySet());
		final ListView<String> customFieldsListView = new ListView<String>("customFieldsListView", customKeys) {

			private static final long serialVersionUID = 1L;

			@Override
			protected void populateItem(ListItem<String> item) {
				String key = item.getModelObject();
				item.add(new Label("customFieldLabel", customFieldsMap.get(key)));

				String value = "";
				if (repositoryModel.customFields != null && repositoryModel.customFields.containsKey(key)) {
					value = repositoryModel.customFields.get(key);
				}
				TextField<String> field = new TextField<String>("customFieldValue", new Model<String>(value));
				item.add(field);
			}
		};
		customFieldsListView.setReuseItems(true);

		CompoundPropertyModel<RepositoryModel> rModel = new CompoundPropertyModel<RepositoryModel>(
				repositoryModel);
		Form<RepositoryModel> form = new Form<RepositoryModel>("editForm", rModel) {

			private static final long serialVersionUID = 1L;

			@Override
			protected void onSubmit() {
				try {
					if (!namePanel.updateModel(repositoryModel)) {
						return;
					}

					// confirm access restriction selection
					if (repositoryModel.accessRestriction == null) {
						error(getString("gb.selectAccessRestriction"));
						return;
					}

					// confirm federation strategy selection
					if (repositoryModel.federationStrategy == null) {
						error(getString("gb.selectFederationStrategy"));
						return;
					}

					// save federation set preferences
					if (repositoryModel.federationStrategy.exceeds(FederationStrategy.EXCLUDE)) {
						repositoryModel.federationSets.clear();
						Iterator<String> sets = federationSetsPalette.getSelectedChoices();
						while (sets.hasNext()) {
							repositoryModel.federationSets.add(sets.next());
						}
					}

					// set author metric exclusions
					String ax = metricAuthorExclusions.getObject();
					if (StringUtils.isEmpty(ax)) {
						repositoryModel.metricAuthorExclusions = new ArrayList<String>();
					} else {
						Set<String> list = new HashSet<String>();
						for (String exclusion : StringUtils.getStringsFromValue(ax,  " ")) {
							if (StringUtils.isEmpty(exclusion)) {
								continue;
							}
							if (exclusion.indexOf(' ') > -1) {
								list.add("\"" + exclusion + "\"");
							} else {
								list.add(exclusion);
							}
						}
						repositoryModel.metricAuthorExclusions = new ArrayList<String>(list);
					}

					// set mailing lists
					String ml = mailingLists.getObject();
					if (StringUtils.isEmpty(ml)) {
						repositoryModel.mailingLists = new ArrayList<String>();
					} else {
						Set<String> list = new HashSet<String>();
						for (String address : ml.split("(,|\\s)")) {
							if (StringUtils.isEmpty(address)) {
								continue;
							}
							list.add(address.toLowerCase());
						}
						repositoryModel.mailingLists = new ArrayList<String>(list);
					}

					// indexed branches
					List<String> indexedBranches = new ArrayList<String>();
					Iterator<String> branches = indexedBranchesPalette.getSelectedChoices();
					while (branches.hasNext()) {
						indexedBranches.add(branches.next());
					}
					repositoryModel.indexedBranches = indexedBranches;

					// pre-receive scripts
					List<String> preReceiveScripts = new ArrayList<String>();
					Iterator<String> pres = preReceivePalette.getSelectedChoices();
					while (pres.hasNext()) {
						preReceiveScripts.add(pres.next());
					}
					repositoryModel.preReceiveScripts = preReceiveScripts;

					// post-receive scripts
					List<String> postReceiveScripts = new ArrayList<String>();
					Iterator<String> post = postReceivePalette.getSelectedChoices();
					while (post.hasNext()) {
						postReceiveScripts.add(post.next());
					}
					repositoryModel.postReceiveScripts = postReceiveScripts;

					// custom fields
					repositoryModel.customFields = new LinkedHashMap<String, String>();
					for (int i = 0; i < customFieldsListView.size(); i++) {
						ListItem<String> child = (ListItem<String>) customFieldsListView.get(i);
						String key = child.getModelObject();

						TextField<String> field = (TextField<String>) child.get("customFieldValue");
						String value = field.getValue();

						repositoryModel.customFields.put(key, value);
					}

					// save the repository
					app().gitblit().updateRepositoryModel(oldName, repositoryModel, isCreate);

					// repository access permissions
					if (repositoryModel.accessRestriction.exceeds(AccessRestrictionType.NONE)) {
						app().gitblit().setUserAccessPermissions(repositoryModel, repositoryUsers);
						app().gitblit().setTeamAccessPermissions(repositoryModel, repositoryTeams);
					}

					//
					// handle ownership changes
					//

					List<Owner> newOwners = new ArrayList<>();
					Iterator<UserChoice> owners = ownersPalette.getSelectedChoices();
					while (owners.hasNext()) {
						String username = owners.next().getUserId();
						UserModel owner = app().users().getUserModel(username);
						newOwners.add(owner);
					}

					app().users().setOwners(repositoryModel, newOwners);

				} catch (GitBlitException e) {
					error(e.getMessage());
					return;
				}
				setRedirect(false);
				setResponsePage(SummaryPage.class, WicketUtils.newRepositoryParameter(repositoryModel.name));
			}
		};

		// Determine available refs & branches
		List<String> availableRefs = new ArrayList<String>();
		List<String> availableBranches = new ArrayList<String>();
		if (!ArrayUtils.isEmpty(repositoryModel.availableRefs)) {
			for (String ref : repositoryModel.availableRefs) {
				if (!ref.startsWith(Constants.R_TICKET)) {
					availableRefs.add(ref);
					if (ref.startsWith(Constants.R_HEADS)) {
						availableBranches.add(Repository.shortenRefName(ref));
					}
				}
			}
		}

		// do not let the browser pre-populate these fields
		form.add(new SimpleAttributeModifier("autocomplete", "off"));


		//
		//
		// GENERAL
		//
		namePanel = new RepositoryNamePanel("namePanel", repositoryModel);
		form.add(namePanel);

		// XXX AccessPolicyPanel is defined later.

		form.add(new ChoiceOption<String>("head",
				getString("gb.headRef"),
				getString("gb.headRefDescription"),
				new PropertyModel<String>(repositoryModel, "HEAD"),
				availableRefs));


		//
		// PERMISSIONS
		//
		form.add(ownersPalette);
		form.add(usersPalette);
		form.add(teamsPalette);

		//
		// TICKETS
		//
		form.add(new BooleanOption("acceptNewPatchsets",
				getString("gb.acceptNewPatchsets"),
				getString("gb.acceptNewPatchsetsDescription"),
				new PropertyModel<Boolean>(repositoryModel, "acceptNewPatchsets")));

		form.add(new BooleanOption("acceptNewTickets",
				getString("gb.acceptNewTickets"),
				getString("gb.acceptNewTicketsDescription"),
				new PropertyModel<Boolean>(repositoryModel, "acceptNewPatchsets")));

		form.add(new BooleanOption("requireApproval",
				getString("gb.requireApproval"),
				getString("gb.requireApprovalDescription"),
				new PropertyModel<Boolean>(repositoryModel, "requireApproval")));

		form.add(new ChoiceOption<String>("mergeTo",
				getString("gb.mergeTo"),
				getString("gb.mergeToDescription"),
				new PropertyModel<String>(repositoryModel, "mergeTo"),
				availableBranches));

		//
		// RECEIVE
		//
		form.add(new BooleanOption("isFrozen",
				getString("gb.isFrozen"),
				getString("gb.isFrozenDescription"),
				new PropertyModel<Boolean>(repositoryModel, "isFrozen")));

		form.add(new BooleanOption("incrementalPushTags",
				getString("gb.enableIncrementalPushTags"),
				getString("gb.useIncrementalPushTagsDescription"),
				new PropertyModel<Boolean>(repositoryModel, "useIncrementalPushTags")));

		final CheckBox verifyCommitter = new CheckBox("checkbox", new PropertyModel<Boolean>(repositoryModel, "verifyCommitter"));
		verifyCommitter.setOutputMarkupId(true);
		form.add(new BooleanOption("verifyCommitter",
				getString("gb.verifyCommitter"),
				getString("gb.verifyCommitterDescription") + "<br/>" + getString("gb.verifyCommitterNote"),
				verifyCommitter).setIsHtmlDescription(true));

		form.add(preReceivePalette);
		form.add(new BulletListPanel("inheritedPreReceive", getString("gb.inherited"), app().repositories()
				.getPreReceiveScriptsInherited(repositoryModel)));
		form.add(postReceivePalette);
		form.add(new BulletListPanel("inheritedPostReceive", getString("gb.inherited"), app().repositories()
				.getPostReceiveScriptsInherited(repositoryModel)));

		WebMarkupContainer customFieldsSection = new WebMarkupContainer("customFieldsSection");
		customFieldsSection.add(customFieldsListView);
		form.add(customFieldsSection.setVisible(!app().settings().getString(Keys.groovy.customFields, "").isEmpty()));

		//
		// FEDERATION
		//
		List<FederationStrategy> federationStrategies = new ArrayList<FederationStrategy>(
				Arrays.asList(FederationStrategy.values()));
		// federation strategies - remove ORIGIN choice if this repository has no origin.
		if (StringUtils.isEmpty(repositoryModel.origin)) {
			federationStrategies.remove(FederationStrategy.FEDERATE_ORIGIN);
		}

		form.add(new ChoiceOption<FederationStrategy>("federationStrategy",
				getString("gb.federationStrategy"),
				getString("gb.federationStrategyDescription"),
				new DropDownChoice<FederationStrategy>(
						"choice",
						new PropertyModel<FederationStrategy>(repositoryModel, "federationStrategy"),
						federationStrategies,
						new FederationTypeRenderer())));

		form.add(federationSetsPalette);

		//
		// SEARCH
		//
		form.add(indexedBranchesPalette);

		//
		// GARBAGE COLLECTION
		//
		boolean gcEnabled = app().settings().getBoolean(Keys.git.enableGarbageCollection, false);
		int defaultGcPeriod = app().settings().getInteger(Keys.git.defaultGarbageCollectionPeriod, 7);
		if (repositoryModel.gcPeriod == 0) {
			repositoryModel.gcPeriod = defaultGcPeriod;
		}
		List<Integer> gcPeriods = Arrays.asList(1, 2, 3, 4, 5, 7, 10, 14 );
		form.add(new ChoiceOption<Integer>("gcPeriod",
				getString("gb.gcPeriod"),
				getString("gb.gcPeriodDescription"),
				new DropDownChoice<Integer>("choice",
						new PropertyModel<Integer>(repositoryModel, "gcPeriod"),
						gcPeriods,
						new GCPeriodRenderer())).setEnabled(gcEnabled));

		form.add(new TextOption("gcThreshold",
				getString("gb.gcThreshold"),
				getString("gb.gcThresholdDescription"),
				"span1",
				new PropertyModel<String>(repositoryModel, "gcThreshold")).setEnabled(gcEnabled));

		//
		// MISCELLANEOUS
		//

		form.add(new TextOption("origin",
				getString("gb.origin"),
				getString("gb.originDescription"),
				"span6",
				new PropertyModel<String>(repositoryModel, "origin")).setEnabled(false));

		form.add(new BooleanOption("showRemoteBranches",
				getString("gb.showRemoteBranches"),
				getString("gb.showRemoteBranchesDescription"),
				new PropertyModel<Boolean>(repositoryModel, "showRemoteBranches")));

		form.add(new BooleanOption("skipSizeCalculation",
				getString("gb.skipSizeCalculation"),
				getString("gb.skipSizeCalculationDescription"),
				new PropertyModel<Boolean>(repositoryModel, "skipSizeCalculation")));

		form.add(new BooleanOption("skipSummaryMetrics",
				getString("gb.skipSummaryMetrics"),
				getString("gb.skipSummaryMetricsDescription"),
				new PropertyModel<Boolean>(repositoryModel, "skipSummaryMetrics")));

		List<Integer> maxActivityCommits  = Arrays.asList(-1, 0, 25, 50, 75, 100, 150, 200, 250, 500);
		form.add(new ChoiceOption<Integer>("maxActivityCommits",
				getString("gb.maxActivityCommits"),
				getString("gb.maxActivityCommitsDescription"),
				new DropDownChoice<Integer>("choice",
						new PropertyModel<Integer>(repositoryModel, "maxActivityCommits"),
						maxActivityCommits,
						new MaxActivityCommitsRenderer())));

		List<CommitMessageRenderer> renderers = Arrays.asList(CommitMessageRenderer.values());
		form.add(new ChoiceOption<CommitMessageRenderer>("commitMessageRenderer",
				getString("gb.commitMessageRenderer"),
				getString("gb.commitMessageRendererDescription"),
				new DropDownChoice<CommitMessageRenderer>("choice",
						new PropertyModel<CommitMessageRenderer>(repositoryModel, "commitMessageRenderer"),
						renderers)));

		metricAuthorExclusions = new Model<String>(ArrayUtils.isEmpty(repositoryModel.metricAuthorExclusions) ? ""
				: StringUtils.flattenStrings(repositoryModel.metricAuthorExclusions, " "));

		form.add(new TextOption("metricAuthorExclusions",
				getString("gb.metricAuthorExclusions"),
				getString("gb.metricAuthorExclusions"),
				"span6",
				metricAuthorExclusions));

		mailingLists = new Model<String>(ArrayUtils.isEmpty(repositoryModel.mailingLists) ? ""
				: StringUtils.flattenStrings(repositoryModel.mailingLists, " "));

		form.add(new TextOption("mailingLists",
				getString("gb.mailingLists"),
				getString("gb.mailingLists"),
				"span6",
				mailingLists));


		// initial enable/disable of permission controls
		if (repositoryModel.accessRestriction.equals(AccessRestrictionType.NONE)) {
			// anonymous everything, disable all controls
			usersPalette.setEnabled(false);
			teamsPalette.setEnabled(false);
			verifyCommitter.setEnabled(false);
		} else {
			// authenticated something
			// enable authorization controls
			verifyCommitter.setEnabled(true);

			boolean allowFineGrainedControls = repositoryModel.authorizationControl.equals(AuthorizationControl.NAMED);
			usersPalette.setEnabled(allowFineGrainedControls);
			teamsPalette.setEnabled(allowFineGrainedControls);
		}

		//
		// ACCESS POLICY PANEL (GENERAL)
		//
		AjaxFormChoiceComponentUpdatingBehavior callback = new AjaxFormChoiceComponentUpdatingBehavior() {

			private static final long serialVersionUID = 1L;

			@Override
			protected void onUpdate(AjaxRequestTarget target) {
				accessPolicyPanel.updateModel(repositoryModel);

				boolean allowAuthorizationControl = repositoryModel.accessRestriction.exceeds(AccessRestrictionType.NONE);
				verifyCommitter.setEnabled(allowAuthorizationControl);

				boolean allowFineGrainedControls = allowAuthorizationControl && repositoryModel.authorizationControl.equals(AuthorizationControl.NAMED);
				usersPalette.setEnabled(allowFineGrainedControls);
				teamsPalette.setEnabled(allowFineGrainedControls);

				if (allowFineGrainedControls) {
					repositoryModel.authorizationControl = AuthorizationControl.NAMED;
				}

				target.addComponent(verifyCommitter);
				target.addComponent(usersPalette);
				target.addComponent(teamsPalette);
			}
		};

		accessPolicyPanel = new AccessPolicyPanel("accessPolicyPanel", repositoryModel, callback);
		form.add(accessPolicyPanel);


		//
		// FORM CONTROLS
		//
		form.add(new Button("save"));
		Button cancel = new Button("cancel") {
			private static final long serialVersionUID = 1L;

			@Override
			public void onSubmit() {
				if (isCreate) {
					setResponsePage(RepositoriesPage.class);
				} else {
					setResponsePage(SummaryPage.class, WicketUtils.newRepositoryParameter(repositoryModel.name));
				}
			}
		};
		cancel.setDefaultFormProcessing(false);
		form.add(cancel);

		// the user can delete if deletions are allowed AND the user is an admin or the personal owner
		// assigned ownership is not sufficient to allow deletion
		boolean canDelete = !isCreate && app().repositories().canDelete(repositoryModel)
				&& user.canDelete(repositoryModel);

		Link<Void> delete = new Link<Void>("delete") {

			private static final long serialVersionUID = 1L;

			@Override
			public void onClick() {
				RepositoryModel latestModel = app().repositories().getRepositoryModel(repositoryModel.name);
				boolean canDelete = app().repositories().canDelete(latestModel);
				if (canDelete) {
					if (app().repositories().deleteRepositoryModel(latestModel)) {
						info(MessageFormat.format(getString("gb.repositoryDeleted"), latestModel));
						if (latestModel.isPersonalRepository()) {
							// redirect to user's profile page
							String username = latestModel.getPersonalRepositoryOwner();
							setResponsePage(UserPage.class, WicketUtils.newUsernameParameter(username));
						} else {
							// redirect to server repositories page
							setResponsePage(RepositoriesPage.class);
						}
					} else {
						error(MessageFormat.format(getString("gb.repositoryDeleteFailed"), latestModel));
					}
				} else {
					error(MessageFormat.format(getString("gb.repositoryDeleteFailed"), latestModel));
				}
			}
		};

		if (canDelete) {
			delete.add(new JavascriptEventConfirmation("onclick", MessageFormat.format(
				getString("gb.deleteRepository"), repositoryModel)));
		}
		form.add(delete.setVisible(canDelete));

		add(form);
	}

	/**
	 * Unfortunately must repeat part of AuthorizaitonStrategy here because that
	 * mechanism does not take PageParameters into consideration, only page
	 * instantiation.
	 *
	 * Repository Owners should be able to edit their repository.
	 */
	private void checkPermissions(RepositoryModel model) {
		boolean authenticateAdmin = app().settings().getBoolean(Keys.web.authenticateAdminPages, true);
		boolean allowAdmin = app().settings().getBoolean(Keys.web.allowAdministration, true);

		GitBlitWebSession session = GitBlitWebSession.get();
		UserModel user = session.getUser();

		if (allowAdmin) {
			if (authenticateAdmin) {
				if (user == null) {
					// No Login Available
					error(getString("gb.errorAdminLoginRequired"), true);
				}
				if (isCreate) {
					// Create Repository
					if (!user.canCreate() && !user.canAdmin()) {
						// Only administrators or permitted users may create
						error(getString("gb.errorOnlyAdminMayCreateRepository"), true);
					}
				} else {
					// Edit Repository
					if (user.canAdmin()) {
						// Admins can edit everything
						isAdmin = true;
						return;
					} else {
						if (!user.isOwner(model)) {
							// User is not an Admin nor Owner
							error(getString("gb.errorOnlyAdminOrOwnerMayEditRepository"), true);
						}
					}
				}
			}
		} else {
			// No Administration Permitted
			error(getString("gb.errorAdministrationDisabled"), true);
		}
	}


	private class FederationTypeRenderer implements IChoiceRenderer<FederationStrategy> {

		private static final long serialVersionUID = 1L;

		private final Map<FederationStrategy, String> map;

		public FederationTypeRenderer() {
			map = getFederationTypes();
		}

		@Override
		public String getDisplayValue(FederationStrategy type) {
			return map.get(type);
		}

		@Override
		public String getIdValue(FederationStrategy type, int index) {
			return Integer.toString(index);
		}
	}

	private class GCPeriodRenderer implements IChoiceRenderer<Integer> {

		private static final long serialVersionUID = 1L;

		public GCPeriodRenderer() {
		}

		@Override
		public String getDisplayValue(Integer value) {
			if (value == 1) {
				return getString("gb.duration.oneDay");
			} else {
				return MessageFormat.format(getString("gb.duration.days"), value);
			}
		}

		@Override
		public String getIdValue(Integer value, int index) {
			return Integer.toString(index);
		}
	}

	private class MaxActivityCommitsRenderer implements IChoiceRenderer<Integer> {

		private static final long serialVersionUID = 1L;

		public MaxActivityCommitsRenderer() {
		}

		@Override
		public String getDisplayValue(Integer value) {
			if (value == -1) {
				return getString("gb.excludeFromActivity");
			} else if (value == 0) {
				return getString("gb.noMaximum");
			} else {
				return value + " " + getString("gb.commits");
			}
		}

		@Override
		public String getIdValue(Integer value, int index) {
			return Integer.toString(index);
		}
	}
}
