/*
 * 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.client;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JRootPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.KeyStroke;

import com.gitblit.Constants;
import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.Constants.AuthorizationControl;
import com.gitblit.Constants.PermissionType;
import com.gitblit.Constants.RegistrantType;
import com.gitblit.Keys;
import com.gitblit.models.RegistrantAccessPermission;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.ServerSettings;
import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.StringUtils;

public class EditUserDialog extends JDialog {

	private static final long serialVersionUID = 1L;

	private final String username;

	private final UserModel user;

	private final ServerSettings settings;

	private boolean isCreate;

	private boolean canceled = true;

	private JTextField usernameField;

	private JPasswordField passwordField;

	private JPasswordField confirmPasswordField;

	private JTextField displayNameField;

	private JTextField emailAddressField;

	private JCheckBox canAdminCheckbox;

	private JCheckBox canForkCheckbox;

	private JCheckBox canCreateCheckbox;

	private JCheckBox notFederatedCheckbox;

	private JCheckBox disabledCheckbox;

	private JTextField organizationalUnitField;

	private JTextField organizationField;

	private JTextField localityField;

	private JTextField stateProvinceField;

	private JTextField countryCodeField;

	private RegistrantPermissionsPanel repositoryPalette;

	private JPalette<TeamModel> teamsPalette;

	private Set<String> usernames;

	public EditUserDialog(int protocolVersion, ServerSettings settings) {
		this(protocolVersion, new UserModel(""), settings);
		this.isCreate = true;
		setTitle(Translation.get("gb.newUser"));
	}

	public EditUserDialog(int protocolVersion, UserModel anUser, ServerSettings settings) {
		super();
		this.username = anUser.username;
		this.user = new UserModel("");
		this.settings = settings;
		this.usernames = new HashSet<String>();
		this.isCreate = false;
		initialize(protocolVersion, anUser);
		setModal(true);
		setTitle(Translation.get("gb.edit") + ": " + anUser.username);
		setIconImage(new ImageIcon(getClass().getResource("/gitblt-favicon.png")).getImage());
	}

	@Override
	protected JRootPane createRootPane() {
		KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
		JRootPane rootPane = new JRootPane();
		rootPane.registerKeyboardAction(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent actionEvent) {
				setVisible(false);
			}
		}, stroke, JComponent.WHEN_IN_FOCUSED_WINDOW);
		return rootPane;
	}

	private void initialize(int protocolVersion, UserModel anUser) {
		usernameField = new JTextField(anUser.username == null ? "" : anUser.username, 25);
		passwordField = new JPasswordField(anUser.password == null ? "" : anUser.password, 25);
		confirmPasswordField = new JPasswordField(anUser.password == null ? "" : anUser.password,
				25);
		displayNameField = new JTextField(anUser.displayName == null ? "" : anUser.displayName, 25);
		emailAddressField = new JTextField(anUser.emailAddress == null ? "" : anUser.emailAddress, 25);
		canAdminCheckbox = new JCheckBox(Translation.get("gb.canAdminDescription"), anUser.canAdmin);
		canForkCheckbox = new JCheckBox(Translation.get("gb.canForkDescription"), anUser.canFork);
		canCreateCheckbox = new JCheckBox(Translation.get("gb.canCreateDescription"), anUser.canCreate);
		notFederatedCheckbox = new JCheckBox(
				Translation.get("gb.excludeFromFederationDescription"),
				anUser.excludeFromFederation);
		disabledCheckbox = new JCheckBox(Translation.get("gb.disableUserDescription"), anUser.disabled);

		organizationalUnitField = new JTextField(anUser.organizationalUnit == null ? "" : anUser.organizationalUnit, 25);
		organizationField = new JTextField(anUser.organization == null ? "" : anUser.organization, 25);
		localityField = new JTextField(anUser.locality == null ? "" : anUser.locality, 25);
		stateProvinceField = new JTextField(anUser.stateProvince == null ? "" : anUser.stateProvince, 25);
		countryCodeField = new JTextField(anUser.countryCode == null ? "" : anUser.countryCode, 15);

		// credentials are optionally controlled by 3rd-party authentication
		usernameField.setEnabled(anUser.isLocalAccount());
		passwordField.setEnabled(anUser.isLocalAccount());
		confirmPasswordField.setEnabled(anUser.isLocalAccount());

		JPanel fieldsPanel = new JPanel(new GridLayout(0, 1));
		fieldsPanel.add(newFieldPanel(Translation.get("gb.username"), usernameField));
		fieldsPanel.add(newFieldPanel(Translation.get("gb.password"), passwordField));
		fieldsPanel.add(newFieldPanel(Translation.get("gb.confirmPassword"), confirmPasswordField));
		fieldsPanel.add(newFieldPanel(Translation.get("gb.displayName"), displayNameField));
		fieldsPanel.add(newFieldPanel(Translation.get("gb.emailAddress"), emailAddressField));
		fieldsPanel.add(newFieldPanel(Translation.get("gb.canAdmin"), canAdminCheckbox));
		fieldsPanel.add(newFieldPanel(Translation.get("gb.canFork"), canForkCheckbox));
		fieldsPanel.add(newFieldPanel(Translation.get("gb.canCreate"), canCreateCheckbox));
		fieldsPanel.add(newFieldPanel(Translation.get("gb.excludeFromFederation"),
				notFederatedCheckbox));
		fieldsPanel.add(newFieldPanel(Translation.get("gb.disableUser"), disabledCheckbox));

		JPanel attributesPanel = new JPanel(new GridLayout(0, 1, 5, 2));
		attributesPanel.add(newFieldPanel(Translation.get("gb.organizationalUnit") + " (OU)", organizationalUnitField));
		attributesPanel.add(newFieldPanel(Translation.get("gb.organization") + " (O)", organizationField));
		attributesPanel.add(newFieldPanel(Translation.get("gb.locality") + " (L)", localityField));
		attributesPanel.add(newFieldPanel(Translation.get("gb.stateProvince") + " (ST)", stateProvinceField));
		attributesPanel.add(newFieldPanel(Translation.get("gb.countryCode") + " (C)", countryCodeField));

		final Insets _insets = new Insets(5, 5, 5, 5);
		repositoryPalette = new RegistrantPermissionsPanel(RegistrantType.REPOSITORY);
		teamsPalette = new JPalette<TeamModel>();

		JPanel fieldsPanelTop = new JPanel(new BorderLayout());
		fieldsPanelTop.add(fieldsPanel, BorderLayout.NORTH);

		JPanel attributesPanelTop = new JPanel(new BorderLayout());
		attributesPanelTop.add(attributesPanel, BorderLayout.NORTH);

		JPanel repositoriesPanel = new JPanel(new BorderLayout()) {

			private static final long serialVersionUID = 1L;

			@Override
			public Insets getInsets() {
				return _insets;
			}
		};
		repositoriesPanel.add(repositoryPalette, BorderLayout.CENTER);

		JPanel teamsPanel = new JPanel(new BorderLayout()) {

			private static final long serialVersionUID = 1L;

			@Override
			public Insets getInsets() {
				return _insets;
			}
		};
		teamsPanel.add(teamsPalette, BorderLayout.CENTER);

		JTabbedPane panel = new JTabbedPane(JTabbedPane.TOP);
		panel.addTab(Translation.get("gb.general"), fieldsPanelTop);
		panel.addTab(Translation.get("gb.attributes"), attributesPanelTop);
		if (protocolVersion > 1) {
			panel.addTab(Translation.get("gb.teamMemberships"), teamsPanel);
		}
		panel.addTab(Translation.get("gb.restrictedRepositories"), repositoriesPanel);

		JButton createButton = new JButton(Translation.get("gb.save"));
		createButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				if (validateFields()) {
					canceled = false;
					setVisible(false);
				}
			}
		});

		JButton cancelButton = new JButton(Translation.get("gb.cancel"));
		cancelButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				canceled = true;
				setVisible(false);
			}
		});

		JPanel controls = new JPanel();
		controls.add(cancelButton);
		controls.add(createButton);

		JPanel centerPanel = new JPanel(new BorderLayout(5, 5)) {

			private static final long serialVersionUID = 1L;

			@Override
			public Insets getInsets() {
				return _insets;
			}
		};
		centerPanel.add(panel, BorderLayout.CENTER);
		centerPanel.add(controls, BorderLayout.SOUTH);

		getContentPane().setLayout(new BorderLayout(5, 5));
		getContentPane().add(centerPanel, BorderLayout.CENTER);
		pack();
	}

	private JPanel newFieldPanel(String label, JComponent comp) {
		JLabel fieldLabel = new JLabel(label);
		fieldLabel.setFont(fieldLabel.getFont().deriveFont(Font.BOLD));
		fieldLabel.setPreferredSize(new Dimension(150, 20));
		JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 0));
		panel.add(fieldLabel);
		panel.add(comp);
		return panel;
	}

	private boolean validateFields() {
		if (StringUtils.isEmpty(usernameField.getText())) {
			error("Please enter a username!");
			return false;
		}
		String uname = usernameField.getText().toLowerCase();
		boolean rename = false;
		// verify username uniqueness on create
		if (isCreate) {
			if (usernames.contains(uname)) {
				error(MessageFormat.format("Username ''{0}'' is unavailable.", uname));
				return false;
			}
		} else {
			// check rename collision
			rename = !StringUtils.isEmpty(username) && !username.equalsIgnoreCase(uname);
			if (rename) {
				if (usernames.contains(uname)) {
					error(MessageFormat.format(
							"Failed to rename ''{0}'' because ''{1}'' already exists.", username,
							uname));
					return false;
				}
			}
		}
		user.username = uname;

		int minLength = settings.get(Keys.realm.minPasswordLength).getInteger(5);
		if (minLength < 4) {
			minLength = 4;
		}

		String password = new String(passwordField.getPassword());
		if (StringUtils.isEmpty(password) || password.length() < minLength) {
			error(MessageFormat.format("Password is too short. Minimum length is {0} characters.",
					minLength));
			return false;
		}
		if (!password.toUpperCase().startsWith(StringUtils.MD5_TYPE)
				&& !password.toUpperCase().startsWith(StringUtils.COMBINED_MD5_TYPE)) {
			String cpw = new String(confirmPasswordField.getPassword());
			if (cpw == null || cpw.length() != password.length()) {
				error("Please confirm the password!");
				return false;
			}
			if (!password.equals(cpw)) {
				error("Passwords do not match!");
				return false;
			}

			// change the cookie
			user.cookie = user.createCookie();

			String type = settings.get(Keys.realm.passwordStorage).getString("md5");
			if (type.equalsIgnoreCase("md5")) {
				// store MD5 digest of password
				user.password = StringUtils.MD5_TYPE + StringUtils.getMD5(password);
			} else if (type.equalsIgnoreCase("combined-md5")) {
				// store MD5 digest of username+password
				user.password = StringUtils.COMBINED_MD5_TYPE
						+ StringUtils.getMD5(user.username + password);
			} else {
				// plain-text password
				user.password = password;
			}
		} else if (rename && password.toUpperCase().startsWith(StringUtils.COMBINED_MD5_TYPE)) {
			error("Gitblit is configured for combined-md5 password hashing. You must enter a new password on account rename.");
			return false;
		} else {
			// no change in password
			user.password = password;
		}

		user.displayName = displayNameField.getText().trim();
		user.emailAddress = emailAddressField.getText().trim();

		user.canAdmin = canAdminCheckbox.isSelected();
		user.canFork = canForkCheckbox.isSelected();
		user.canCreate = canCreateCheckbox.isSelected();
		user.excludeFromFederation = notFederatedCheckbox.isSelected();
		user.disabled = disabledCheckbox.isSelected();

		user.organizationalUnit = organizationalUnitField.getText().trim();
		user.organization = organizationField.getText().trim();
		user.locality = localityField.getText().trim();
		user.stateProvince = stateProvinceField.getText().trim();
		user.countryCode = countryCodeField.getText().trim();

		for (RegistrantAccessPermission rp : repositoryPalette.getPermissions()) {
			user.setRepositoryPermission(rp.registrant, rp.permission);
		}

		user.teams.clear();
		user.teams.addAll(teamsPalette.getSelections());
		return true;
	}

	private void error(String message) {
		JOptionPane.showMessageDialog(EditUserDialog.this, message, Translation.get("gb.error"),
				JOptionPane.ERROR_MESSAGE);
	}

	public void setUsers(List<UserModel> users) {
		usernames.clear();
		for (UserModel user : users) {
			usernames.add(user.username.toLowerCase());
		}
	}

	public void setRepositories(List<RepositoryModel> repositories, List<RegistrantAccessPermission> permissions) {
		Map<String, RepositoryModel> repoMap = new HashMap<String, RepositoryModel>();
		List<String> restricted = new ArrayList<String>();
		for (RepositoryModel repo : repositories) {
			// exclude Owner or personal repositories
			if (!repo.isOwner(username) && !repo.isUsersPersonalRepository(username)) {
				if (repo.accessRestriction.exceeds(AccessRestrictionType.NONE)
						&& repo.authorizationControl.equals(AuthorizationControl.NAMED)) {
					restricted.add(repo.name);
				}
			}
			repoMap.put(repo.name.toLowerCase(), repo);
		}
		StringUtils.sortRepositorynames(restricted);

		List<String> list = new ArrayList<String>();
		// repositories
		list.add(".*");

		String prefix;
		if (settings.hasKey(Keys.git.userRepositoryPrefix)) {
			prefix = settings.get(Keys.git.userRepositoryPrefix).currentValue;
			if (StringUtils.isEmpty(prefix)) {
				prefix = Constants.DEFAULT_USER_REPOSITORY_PREFIX;
			}
		} else {
			prefix = Constants.DEFAULT_USER_REPOSITORY_PREFIX;
		}

		if (prefix.length() == 1) {
			// all repositories excluding personal repositories
			list.add("[^" + prefix + "].*");
		}

		String lastProject = null;
		for (String repo : restricted) {
			String projectPath = StringUtils.getFirstPathElement(repo).toLowerCase();
			if (lastProject == null || !lastProject.equalsIgnoreCase(projectPath)) {
				lastProject = projectPath;
				if (!StringUtils.isEmpty(projectPath)) {
					// regex for all repositories within a project
					list.add(projectPath + "/.*");
				}
			}
			list.add(repo);
		}

		// remove repositories for which user already has a permission
		if (permissions == null) {
			permissions = new ArrayList<RegistrantAccessPermission>();
		} else {
			for (RegistrantAccessPermission rp : permissions) {
				list.remove(rp.registrant.toLowerCase());
			}
		}

		// update owner and missing permissions for editing
		for (RegistrantAccessPermission permission : permissions) {
			if (permission.mutable && PermissionType.EXPLICIT.equals(permission.permissionType)) {
				// Ensure this is NOT an owner permission - which is non-editable
				// We don't know this from within the usermodel, ownership is a
				// property of a repository.
				RepositoryModel rm = repoMap.get(permission.registrant.toLowerCase());
				if (rm == null) {
					permission.permissionType = PermissionType.MISSING;
					permission.mutable = false;
					continue;
				}
				boolean isOwner = rm.isOwner(username);
				if (isOwner) {
					permission.permissionType = PermissionType.OWNER;
					permission.mutable = false;
				}
			}
		}

		repositoryPalette.setObjects(list, permissions);
	}

	public void setTeams(List<TeamModel> teams, List<TeamModel> selected) {
		Collections.sort(teams);
		if (selected != null) {
			Collections.sort(selected);
		}
		teamsPalette.setObjects(teams, selected);
	}

	public UserModel getUser() {
		if (canceled) {
			return null;
		}
		return user;
	}
}
