/*
 * Copyright 2012 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.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.markup.html.basic.Label;
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.panel.Fragment;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.OddEvenItem;
import org.apache.wicket.markup.repeater.RefreshingView;
import org.apache.wicket.markup.repeater.util.ModelIteratorAdapter;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.IModel;
import org.eclipse.jgit.lib.PersonIdent;

import com.gitblit.Constants.AccessPermission;
import com.gitblit.Constants.PermissionType;
import com.gitblit.Constants.RegistrantType;
import com.gitblit.models.RegistrantAccessPermission;
import com.gitblit.models.UserModel;
import com.gitblit.utils.DeepCopier;
import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.WicketUtils;

/**
 * Allows user to manipulate registrant access permissions.
 *
 * @author James Moger
 *
 */
public class RegistrantPermissionsPanel extends BasePanel {

	private static final long serialVersionUID = 1L;

	public enum Show {
		specified, mutable, effective;

		public boolean show(RegistrantAccessPermission ap) {
			switch (this) {
			case specified:
				return ap.mutable || ap.isOwner();
			case mutable:
				return ap.mutable;
			case effective:
				return true;
			default:
				return true;
			}
		}
	}

	private Show activeState = Show.mutable;

	public RegistrantPermissionsPanel(String wicketId, RegistrantType registrantType, List<String> allRegistrants, final List<RegistrantAccessPermission> permissions, final Map<AccessPermission, String> translations) {
		super(wicketId);
		setOutputMarkupId(true);

		/*
		 * Permission view toggle buttons
		 */
		Form<Void> permissionToggleForm = new Form<Void>("permissionToggleForm");
		permissionToggleForm.add(new ShowStateButton("showSpecified", Show.specified));
		permissionToggleForm.add(new ShowStateButton("showMutable", Show.mutable));
		permissionToggleForm.add(new ShowStateButton("showEffective", Show.effective));
		add(permissionToggleForm);

		/*
		 * Permission repeating display
		 */
		RefreshingView<RegistrantAccessPermission> dataView = new RefreshingView<RegistrantAccessPermission>("permissionRow") {
			private static final long serialVersionUID = 1L;

			@Override
            protected Iterator<IModel<RegistrantAccessPermission>> getItemModels() {
                // the iterator returns RepositoryPermission objects, but we need it to
                // return models
                return new ModelIteratorAdapter<RegistrantAccessPermission>(permissions.iterator()) {
                    @Override
                    protected IModel<RegistrantAccessPermission> model(RegistrantAccessPermission permission) {
                        return new CompoundPropertyModel<RegistrantAccessPermission>(permission);
                    }
                };
            }

            @Override
            protected Item<RegistrantAccessPermission> newItem(String id, int index, IModel<RegistrantAccessPermission> model) {
                // this item sets markup class attribute to either 'odd' or
                // 'even' for decoration
                return new OddEvenItem<RegistrantAccessPermission>(id, index, model);
            }

			@Override
			public void populateItem(final Item<RegistrantAccessPermission> item) {
				final RegistrantAccessPermission entry = item.getModelObject();
				if (RegistrantType.REPOSITORY.equals(entry.registrantType)) {
					String repoName = StringUtils.stripDotGit(entry.registrant);
					if (!entry.isMissing() && StringUtils.findInvalidCharacter(repoName) == null) {
						// repository, strip .git and show swatch
						Fragment repositoryFragment = new Fragment("registrant", "repositoryRegistrant", RegistrantPermissionsPanel.this);
						Component swatch = new Label("repositorySwatch", "&nbsp;").setEscapeModelStrings(false);
						WicketUtils.setCssBackground(swatch, entry.toString());
						repositoryFragment.add(swatch);
						Label registrant = new Label("repositoryName", repoName);
						repositoryFragment.add(registrant);
						item.add(repositoryFragment);
					} else {
						// regex or missing
						Label label = new Label("registrant", entry.registrant);
						WicketUtils.setCssStyle(label, "font-weight: bold;");
						item.add(label);
					}
				} else if (RegistrantType.USER.equals(entry.registrantType)) {
					// user
					PersonIdent ident = new PersonIdent(entry.registrant, "");
					UserModel user = app().users().getUserModel(entry.registrant);
					if (user != null) {
						ident = new PersonIdent(user.getDisplayName(), user.emailAddress == null ? user.getDisplayName() : user.emailAddress);
					}

					Fragment userFragment = new Fragment("registrant", "userRegistrant", RegistrantPermissionsPanel.this);
					userFragment.add(new AvatarImage("userAvatar", ident, 20));
					userFragment.add(new Label("userName", entry.registrant));
					item.add(userFragment);
				} else {
					// team
					Fragment teamFragment = new Fragment("registrant", "teamRegistrant", RegistrantPermissionsPanel.this);
					teamFragment.add(new Label("teamName", entry.registrant));
					item.add(teamFragment);
				}
				switch (entry.permissionType) {
				case ADMINISTRATOR:
					Label administrator = new Label("pType", entry.source == null ? getString("gb.administrator") : entry.source);
					WicketUtils.setHtmlTooltip(administrator, getString("gb.administratorPermission"));
					WicketUtils.setCssClass(administrator, "label label-inverse");
					item.add(administrator);
					break;
				case OWNER:
					Label owner = new Label("pType", getString("gb.owner"));
					WicketUtils.setHtmlTooltip(owner, getString("gb.ownerPermission"));
					WicketUtils.setCssClass(owner, "label label-info");
					item.add(owner);
					break;
				case TEAM:
					Label team = new Label("pType", entry.source == null ? getString("gb.team") : entry.source);
					WicketUtils.setHtmlTooltip(team, MessageFormat.format(getString("gb.teamPermission"), entry.source));
					WicketUtils.setCssClass(team, "label label-success");
					item.add(team);
					break;
				case REGEX:
					Label regex = new Label("pType", "regex");
					if (!StringUtils.isEmpty(entry.source)) {
						WicketUtils.setHtmlTooltip(regex, MessageFormat.format(getString("gb.regexPermission"), entry.source));
					}
					WicketUtils.setCssClass(regex, "label");
					item.add(regex);
					break;
				default:
					if (entry.isMissing()) {
						// repository is missing, this permission will be removed on save
						Label missing = new Label("pType", getString("gb.missing"));
						WicketUtils.setCssClass(missing, "label label-important");
						WicketUtils.setHtmlTooltip(missing, getString("gb.missingPermission"));
						item.add(missing);
					} else {
						// standard permission
						item.add(new Label("pType", "").setVisible(false));
					}
					break;
				}

				item.setVisible(activeState.show(entry));

				// use ajax to get immediate update of permission level change
				// otherwise we can lose it if they change levels and then add
				// a new repository permission
				final DropDownChoice<AccessPermission> permissionChoice = new DropDownChoice<AccessPermission>(
						"permission", Arrays.asList(AccessPermission.values()), new AccessPermissionRenderer(translations));
				// only allow changing an explicitly defined permission
				// this is designed to prevent changing a regex permission in
				// a repository
				permissionChoice.setEnabled(entry.mutable);
				permissionChoice.setOutputMarkupId(true);
				if (entry.mutable) {
					permissionChoice.add(new AjaxFormComponentUpdatingBehavior("onchange") {

						private static final long serialVersionUID = 1L;

						@Override
						protected void onUpdate(AjaxRequestTarget target) {
							target.addComponent(permissionChoice);
						}
					});
				}

				item.add(permissionChoice);
			}
		};
		add(dataView);
		setOutputMarkupId(true);

		// filter out registrants we already have permissions for
		final List<String> registrants = new ArrayList<String>(allRegistrants);
		for (RegistrantAccessPermission rp : permissions) {
			if (rp.mutable) {
				// remove editable duplicates
				// this allows for specifying an explicit permission
				registrants.remove(rp.registrant);
			} else if (rp.isAdmin()) {
				// administrators can not have their permission changed
				registrants.remove(rp.registrant);
			} else if (rp.isOwner()) {
				// owners can not have their permission changed
				registrants.remove(rp.registrant);
			}
		}

		/*
		 * Add permission form
		 */
		IModel<RegistrantAccessPermission> addPermissionModel = new CompoundPropertyModel<RegistrantAccessPermission>(new RegistrantAccessPermission(registrantType));
		Form<RegistrantAccessPermission> addPermissionForm = new Form<RegistrantAccessPermission>("addPermissionForm", addPermissionModel);
		addPermissionForm.add(new DropDownChoice<String>("registrant", registrants));
		addPermissionForm.add(new DropDownChoice<AccessPermission>("permission", Arrays
				.asList(AccessPermission.NEWPERMISSIONS), new AccessPermissionRenderer(translations)));
		AjaxButton button = new AjaxButton("addPermissionButton", addPermissionForm) {

			private static final long serialVersionUID = 1L;

			@Override
			protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
				// add permission to our list
				RegistrantAccessPermission rp = (RegistrantAccessPermission) form.getModel().getObject();
				if (rp.permission == null) {
					return;
				}
				if (rp.registrant == null) {
					return;
				}
				RegistrantAccessPermission copy = DeepCopier.copy(rp);
				if (StringUtils.findInvalidCharacter(copy.registrant) != null) {
					copy.permissionType = PermissionType.REGEX;
					copy.source = copy.registrant;
				}
				permissions.add(copy);

				// resort permissions after insert to convey idea of eval order
				Collections.sort(permissions);

				// remove registrant from available choices
				registrants.remove(rp.registrant);

				// force the panel to refresh
				target.addComponent(RegistrantPermissionsPanel.this);
			}
		};
		addPermissionForm.add(button);

		// only show add permission form if we have a registrant choice
		add(addPermissionForm.setVisible(registrants.size() > 0));
	}

	@Override
	protected boolean getStatelessHint()
	{
		return false;
	}


	private class AccessPermissionRenderer implements IChoiceRenderer<AccessPermission> {

		private static final long serialVersionUID = 1L;

		private final Map<AccessPermission, String> map;

		public AccessPermissionRenderer(Map<AccessPermission, String> map) {
			this.map = map;
		}

		@Override
		public String getDisplayValue(AccessPermission type) {
			return map.get(type);
		}

		@Override
		public String getIdValue(AccessPermission type, int index) {
			return Integer.toString(index);
		}
	}

	private class ShowStateButton extends AjaxButton {
		private static final long serialVersionUID = 1L;

		Show buttonState;

		public ShowStateButton(String wicketId, Show state) {
			super(wicketId);
			this.buttonState = state;
			setOutputMarkupId(true);
		}

		@Override
		protected void onBeforeRender()
		{
			String cssClass = "btn";
			if (buttonState.equals(RegistrantPermissionsPanel.this.activeState)) {
				cssClass = "btn btn-info active";
			}
			WicketUtils.setCssClass(this, cssClass);
			super.onBeforeRender();
		}

		@Override
		protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
			RegistrantPermissionsPanel.this.activeState = buttonState;
			target.addComponent(RegistrantPermissionsPanel.this);
		}
	};
}
