/*
 * 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;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gitblit.Constants.AccessPermission;
import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.DeepCopier;
import com.gitblit.utils.StringUtils;

/**
 * FileUserService is Gitblit's original default user service implementation.
 * 
 * Users and their repository memberships are stored in a simple properties file
 * which is cached and dynamically reloaded when modified.
 * 
 * This class was deprecated in Gitblit 0.8.0 in favor of ConfigUserService
 * which is still a human-readable, editable, plain-text file but it is more
 * flexible for storing additional fields.
 * 
 * @author James Moger
 * 
 */
@Deprecated
public class FileUserService extends FileSettings implements IUserService {

	private final Logger logger = LoggerFactory.getLogger(FileUserService.class);

	private final Map<String, String> cookies = new ConcurrentHashMap<String, String>();

	private final Map<String, TeamModel> teams = new ConcurrentHashMap<String, TeamModel>();

	public FileUserService(File realmFile) {
		super(realmFile.getAbsolutePath());
	}

	/**
	 * Setup the user service.
	 * 
	 * @param settings
	 * @since 0.7.0
	 */
	@Override
	public void setup(IStoredSettings settings) {
	}

	/**
	 * Does the user service support changes to credentials?
	 * 
	 * @return true or false
	 * @since 1.0.0
	 */
	@Override
	public boolean supportsCredentialChanges() {
		return true;
	}

	/**
	 * Does the user service support changes to user display name?
	 * 
	 * @return true or false
	 * @since 1.0.0
	 */
	@Override
	public boolean supportsDisplayNameChanges() {
		return false;
	}

	/**
	 * Does the user service support changes to user email address?
	 * 
	 * @return true or false
	 * @since 1.0.0
	 */
	@Override
	public boolean supportsEmailAddressChanges() {
		return false;
	}

	/**
	 * Does the user service support changes to team memberships?
	 * 
	 * @return true or false
	 * @since 1.0.0
	 */	
	public boolean supportsTeamMembershipChanges() {
		return true;
	}

	/**
	 * Does the user service support cookie authentication?
	 * 
	 * @return true or false
	 */
	@Override
	public boolean supportsCookies() {
		return true;
	}

	/**
	 * Returns the cookie value for the specified user.
	 * 
	 * @param model
	 * @return cookie value
	 */
	@Override
	public String getCookie(UserModel model) {
		if (!StringUtils.isEmpty(model.cookie)) {
			return model.cookie;
		}
		Properties allUsers = super.read();
		String value = allUsers.getProperty(model.username);
		String[] roles = value.split(",");
		String password = roles[0];
		String cookie = StringUtils.getSHA1(model.username + password);
		return cookie;
	}

	/**
	 * Authenticate a user based on their cookie.
	 * 
	 * @param cookie
	 * @return a user object or null
	 */
	@Override
	public UserModel authenticate(char[] cookie) {
		String hash = new String(cookie);
		if (StringUtils.isEmpty(hash)) {
			return null;
		}
		read();
		UserModel model = null;
		if (cookies.containsKey(hash)) {
			String username = cookies.get(hash);
			model = getUserModel(username);
		}
		return model;
	}

	/**
	 * Authenticate a user based on a username and password.
	 * 
	 * @param username
	 * @param password
	 * @return a user object or null
	 */
	@Override
	public UserModel authenticate(String username, char[] password) {
		Properties allUsers = read();
		String userInfo = allUsers.getProperty(username);
		if (StringUtils.isEmpty(userInfo)) {
			return null;
		}
		UserModel returnedUser = null;
		UserModel user = getUserModel(username);
		if (user.password.startsWith(StringUtils.MD5_TYPE)) {
			// password digest
			String md5 = StringUtils.MD5_TYPE + StringUtils.getMD5(new String(password));
			if (user.password.equalsIgnoreCase(md5)) {
				returnedUser = user;
			}
		} else if (user.password.startsWith(StringUtils.COMBINED_MD5_TYPE)) {
			// username+password digest
			String md5 = StringUtils.COMBINED_MD5_TYPE
					+ StringUtils.getMD5(username.toLowerCase() + new String(password));
			if (user.password.equalsIgnoreCase(md5)) {
				returnedUser = user;
			}
		} else if (user.password.equals(new String(password))) {
			// plain-text password
			returnedUser = user;
		}
		return returnedUser;
	}

	/**
	 * Logout a user.
	 * 
	 * @param user
	 */
	@Override
	public void logout(UserModel user) {	
	}

	/**
	 * Retrieve the user object for the specified username.
	 * 
	 * @param username
	 * @return a user object or null
	 */
	@Override
	public UserModel getUserModel(String username) {
		Properties allUsers = read();
		String userInfo = allUsers.getProperty(username.toLowerCase());
		if (userInfo == null) {
			return null;
		}
		UserModel model = new UserModel(username.toLowerCase());
		String[] userValues = userInfo.split(",");
		model.password = userValues[0];
		for (int i = 1; i < userValues.length; i++) {
			String role = userValues[i];
			switch (role.charAt(0)) {
			case '#':
				// Permissions
				if (role.equalsIgnoreCase(Constants.ADMIN_ROLE)) {
					model.canAdmin = true;
				} else if (role.equalsIgnoreCase(Constants.FORK_ROLE)) {
					model.canFork = true;
				} else if (role.equalsIgnoreCase(Constants.CREATE_ROLE)) {
					model.canCreate = true;
				} else if (role.equalsIgnoreCase(Constants.NOT_FEDERATED_ROLE)) {
					model.excludeFromFederation = true;
				}
				break;
			default:
				model.addRepositoryPermission(role);
			}
		}
		// set the teams for the user
		for (TeamModel team : teams.values()) {
			if (team.hasUser(username)) {
				model.teams.add(DeepCopier.copy(team));
			}
		}
		return model;
	}

	/**
	 * Updates/writes a complete user object.
	 * 
	 * @param model
	 * @return true if update is successful
	 */
	@Override
	public boolean updateUserModel(UserModel model) {
		return updateUserModel(model.username, model);
	}

	/**
	 * Updates/writes all specified user objects.
	 * 
	 * @param models a list of user models
	 * @return true if update is successful
	 * @since 1.2.0
	 */
	@Override
	public boolean updateUserModels(Collection<UserModel> models) {
		try {			
			Properties allUsers = read();
			for (UserModel model : models) {
				updateUserCache(allUsers, model.username, model);
			}
			write(allUsers);
			return true;
		} catch (Throwable t) {
			logger.error(MessageFormat.format("Failed to update {0} user models!", models.size()),
					t);
		}
		return false;
	}

	/**
	 * Updates/writes and replaces a complete user object keyed by username.
	 * This method allows for renaming a user.
	 * 
	 * @param username
	 *            the old username
	 * @param model
	 *            the user object to use for username
	 * @return true if update is successful
	 */
	@Override
	public boolean updateUserModel(String username, UserModel model) {
		try {			
			Properties allUsers = read();
			updateUserCache(allUsers, username, model);
			write(allUsers);
			return true;
		} catch (Throwable t) {
			logger.error(MessageFormat.format("Failed to update user model {0}!", model.username),
					t);
		}
		return false;
	}
	
	/**
	 * Updates/writes and replaces a complete user object keyed by username.
	 * This method allows for renaming a user.
	 * 
	 * @param username
	 *            the old username
	 * @param model
	 *            the user object to use for username
	 * @return true if update is successful
	 */
	private boolean updateUserCache(Properties allUsers, String username, UserModel model) {
		try {			
			UserModel oldUser = getUserModel(username);
			List<String> roles;
			if (model.permissions == null) {
				roles = new ArrayList<String>();
			} else {
				// discrete repository permissions
				roles = new ArrayList<String>();
				for (Map.Entry<String, AccessPermission> entry : model.permissions.entrySet()) {
					if (entry.getValue().exceeds(AccessPermission.NONE)) {
						// code:repository (e.g. RW+:~james/myrepo.git
						roles.add(entry.getValue().asRole(entry.getKey()));
					}
				}
			}

			// Permissions
			if (model.canAdmin) {
				roles.add(Constants.ADMIN_ROLE);
			}
			if (model.canFork) {
				roles.add(Constants.FORK_ROLE);
			}
			if (model.canCreate) {
				roles.add(Constants.CREATE_ROLE);
			}
			if (model.excludeFromFederation) {
				roles.add(Constants.NOT_FEDERATED_ROLE);
			}

			StringBuilder sb = new StringBuilder();
			if (!StringUtils.isEmpty(model.password)) {
				sb.append(model.password);
			}
			sb.append(',');
			for (String role : roles) {
				sb.append(role);
				sb.append(',');
			}
			// trim trailing comma
			sb.setLength(sb.length() - 1);
			allUsers.remove(username.toLowerCase());
			allUsers.put(model.username.toLowerCase(), sb.toString());

			// null check on "final" teams because JSON-sourced UserModel
			// can have a null teams object
			if (model.teams != null) {
				// update team cache
				for (TeamModel team : model.teams) {
					TeamModel t = getTeamModel(team.name);
					if (t == null) {
						// new team
						t = team;
					}
					t.removeUser(username);
					t.addUser(model.username);
					updateTeamCache(allUsers, t.name, t);
				}

				// check for implicit team removal
				if (oldUser != null) {
					for (TeamModel team : oldUser.teams) {
						if (!model.isTeamMember(team.name)) {
							team.removeUser(username);
							updateTeamCache(allUsers, team.name, team);
						}
					}
				}
			}
			return true;
		} catch (Throwable t) {
			logger.error(MessageFormat.format("Failed to update user model {0}!", model.username),
					t);
		}
		return false;
	}

	/**
	 * Deletes the user object from the user service.
	 * 
	 * @param model
	 * @return true if successful
	 */
	@Override
	public boolean deleteUserModel(UserModel model) {
		return deleteUser(model.username);
	}

	/**
	 * Delete the user object with the specified username
	 * 
	 * @param username
	 * @return true if successful
	 */
	@Override
	public boolean deleteUser(String username) {
		try {
			// Read realm file
			Properties allUsers = read();
			UserModel user = getUserModel(username);
			allUsers.remove(username);
			for (TeamModel team : user.teams) {
				TeamModel t = getTeamModel(team.name);
				if (t == null) {
					// new team
					t = team;
				}
				t.removeUser(username);
				updateTeamCache(allUsers, t.name, t);
			}
			write(allUsers);
			return true;
		} catch (Throwable t) {
			logger.error(MessageFormat.format("Failed to delete user {0}!", username), t);
		}
		return false;
	}

	/**
	 * Returns the list of all users available to the login service.
	 * 
	 * @return list of all usernames
	 */
	@Override
	public List<String> getAllUsernames() {
		Properties allUsers = read();
		List<String> list = new ArrayList<String>();
		for (String user : allUsers.stringPropertyNames()) {
			if (user.charAt(0) == '@') {
				// skip team user definitions
				continue;
			}
			list.add(user);
		}
		Collections.sort(list);
		return list;
	}

	/**
	 * Returns the list of all users available to the login service.
	 * 
	 * @return list of all usernames
	 */
	@Override
	public List<UserModel> getAllUsers() {
		read();
		List<UserModel> list = new ArrayList<UserModel>();
		for (String username : getAllUsernames()) {
			list.add(getUserModel(username));
		}
		Collections.sort(list);
		return list;
	}

	/**
	 * Returns the list of all users who are allowed to bypass the access
	 * restriction placed on the specified repository.
	 * 
	 * @param role
	 *            the repository name
	 * @return list of all usernames that can bypass the access restriction
	 */
	@Override
	public List<String> getUsernamesForRepositoryRole(String role) {
		List<String> list = new ArrayList<String>();
		try {
			Properties allUsers = read();
			for (String username : allUsers.stringPropertyNames()) {
				if (username.charAt(0) == '@') {
					continue;
				}
				String value = allUsers.getProperty(username);
				String[] values = value.split(",");
				// skip first value (password)
				for (int i = 1; i < values.length; i++) {
					String r = values[i];
					if (r.equalsIgnoreCase(role)) {
						list.add(username);
						break;
					}
				}
			}
		} catch (Throwable t) {
			logger.error(MessageFormat.format("Failed to get usernames for role {0}!", role), t);
		}
		Collections.sort(list);
		return list;
	}

	/**
	 * Sets the list of all users who are allowed to bypass the access
	 * restriction placed on the specified repository.
	 * 
	 * @param role
	 *            the repository name
	 * @param usernames
	 * @return true if successful
	 */
	@Override
	public boolean setUsernamesForRepositoryRole(String role, List<String> usernames) {
		try {
			Set<String> specifiedUsers = new HashSet<String>(usernames);
			Set<String> needsAddRole = new HashSet<String>(specifiedUsers);
			Set<String> needsRemoveRole = new HashSet<String>();

			// identify users which require add and remove role
			Properties allUsers = read();
			for (String username : allUsers.stringPropertyNames()) {
				String value = allUsers.getProperty(username);
				String[] values = value.split(",");
				// skip first value (password)
				for (int i = 1; i < values.length; i++) {
					String r = values[i];
					if (r.equalsIgnoreCase(role)) {
						// user has role, check against revised user list
						if (specifiedUsers.contains(username)) {
							needsAddRole.remove(username);
						} else {
							// remove role from user
							needsRemoveRole.add(username);
						}
						break;
					}
				}
			}

			// add roles to users
			for (String user : needsAddRole) {
				String userValues = allUsers.getProperty(user);
				userValues += "," + role;
				allUsers.put(user, userValues);
			}

			// remove role from user
			for (String user : needsRemoveRole) {
				String[] values = allUsers.getProperty(user).split(",");
				String password = values[0];
				StringBuilder sb = new StringBuilder();
				sb.append(password);
				sb.append(',');

				// skip first value (password)
				for (int i = 1; i < values.length; i++) {
					String value = values[i];
					if (!value.equalsIgnoreCase(role)) {
						sb.append(value);
						sb.append(',');
					}
				}
				sb.setLength(sb.length() - 1);

				// update properties
				allUsers.put(user, sb.toString());
			}

			// persist changes
			write(allUsers);
			return true;
		} catch (Throwable t) {
			logger.error(MessageFormat.format("Failed to set usernames for role {0}!", role), t);
		}
		return false;
	}

	/**
	 * Renames a repository role.
	 * 
	 * @param oldRole
	 * @param newRole
	 * @return true if successful
	 */
	@Override
	public boolean renameRepositoryRole(String oldRole, String newRole) {
		try {
			Properties allUsers = read();
			Set<String> needsRenameRole = new HashSet<String>();

			// identify users which require role rename
			for (String username : allUsers.stringPropertyNames()) {
				String value = allUsers.getProperty(username);
				String[] roles = value.split(",");
				// skip first value (password)
				for (int i = 1; i < roles.length; i++) {
					String repository = AccessPermission.repositoryFromRole(roles[i]);
					if (repository.equalsIgnoreCase(oldRole)) {
						needsRenameRole.add(username);
						break;
					}
				}
			}

			// rename role for identified users
			for (String user : needsRenameRole) {
				String userValues = allUsers.getProperty(user);
				String[] values = userValues.split(",");
				String password = values[0];
				StringBuilder sb = new StringBuilder();
				sb.append(password);
				sb.append(',');
				sb.append(newRole);
				sb.append(',');

				// skip first value (password)
				for (int i = 1; i < values.length; i++) {
					String repository = AccessPermission.repositoryFromRole(values[i]);
					if (repository.equalsIgnoreCase(oldRole)) {
						AccessPermission permission = AccessPermission.permissionFromRole(values[i]);
						sb.append(permission.asRole(newRole));
						sb.append(',');
					} else {
						sb.append(values[i]);
						sb.append(',');
					}
				}
				sb.setLength(sb.length() - 1);

				// update properties
				allUsers.put(user, sb.toString());
			}

			// persist changes
			write(allUsers);
			return true;
		} catch (Throwable t) {
			logger.error(
					MessageFormat.format("Failed to rename role {0} to {1}!", oldRole, newRole), t);
		}
		return false;
	}

	/**
	 * Removes a repository role from all users.
	 * 
	 * @param role
	 * @return true if successful
	 */
	@Override
	public boolean deleteRepositoryRole(String role) {
		try {
			Properties allUsers = read();
			Set<String> needsDeleteRole = new HashSet<String>();

			// identify users which require role rename
			for (String username : allUsers.stringPropertyNames()) {
				String value = allUsers.getProperty(username);
				String[] roles = value.split(",");
				// skip first value (password)
				for (int i = 1; i < roles.length; i++) {					
					String repository = AccessPermission.repositoryFromRole(roles[i]);
					if (repository.equalsIgnoreCase(role)) {
						needsDeleteRole.add(username);
						break;
					}
				}
			}

			// delete role for identified users
			for (String user : needsDeleteRole) {
				String userValues = allUsers.getProperty(user);
				String[] values = userValues.split(",");
				String password = values[0];
				StringBuilder sb = new StringBuilder();
				sb.append(password);
				sb.append(',');
				// skip first value (password)
				for (int i = 1; i < values.length; i++) {					
					String repository = AccessPermission.repositoryFromRole(values[i]);
					if (!repository.equalsIgnoreCase(role)) {
						sb.append(values[i]);
						sb.append(',');
					}
				}
				sb.setLength(sb.length() - 1);

				// update properties
				allUsers.put(user, sb.toString());
			}

			// persist changes
			write(allUsers);
			return true;
		} catch (Throwable t) {
			logger.error(MessageFormat.format("Failed to delete role {0}!", role), t);
		}
		return false;
	}

	/**
	 * Writes the properties file.
	 * 
	 * @param properties
	 * @throws IOException
	 */
	private void write(Properties properties) throws IOException {
		// Write a temporary copy of the users file
		File realmFileCopy = new File(propertiesFile.getAbsolutePath() + ".tmp");
		FileWriter writer = new FileWriter(realmFileCopy);
		properties
				.store(writer,
						" Gitblit realm file format:\n   username=password,\\#permission,repository1,repository2...\n   @teamname=!username1,!username2,!username3,repository1,repository2...");
		writer.close();
		// If the write is successful, delete the current file and rename
		// the temporary copy to the original filename.
		if (realmFileCopy.exists() && realmFileCopy.length() > 0) {
			if (propertiesFile.exists()) {
				if (!propertiesFile.delete()) {
					throw new IOException(MessageFormat.format("Failed to delete {0}!",
							propertiesFile.getAbsolutePath()));
				}
			}
			if (!realmFileCopy.renameTo(propertiesFile)) {
				throw new IOException(MessageFormat.format("Failed to rename {0} to {1}!",
						realmFileCopy.getAbsolutePath(), propertiesFile.getAbsolutePath()));
			}
		} else {
			throw new IOException(MessageFormat.format("Failed to save {0}!",
					realmFileCopy.getAbsolutePath()));
		}
	}

	/**
	 * Reads the properties file and rebuilds the in-memory cookie lookup table.
	 */
	@Override
	protected synchronized Properties read() {
		long lastRead = lastModified();
		boolean reload = forceReload();
		Properties allUsers = super.read();
		if (reload || (lastRead != lastModified())) {
			// reload hash cache
			cookies.clear();
			teams.clear();

			for (String username : allUsers.stringPropertyNames()) {
				String value = allUsers.getProperty(username);
				String[] roles = value.split(",");
				if (username.charAt(0) == '@') {
					// team definition
					TeamModel team = new TeamModel(username.substring(1));
					List<String> repositories = new ArrayList<String>();
					List<String> users = new ArrayList<String>();
					List<String> mailingLists = new ArrayList<String>();
					List<String> preReceive = new ArrayList<String>();
					List<String> postReceive = new ArrayList<String>();
					for (String role : roles) {
						if (role.charAt(0) == '!') {
							users.add(role.substring(1));
						} else if (role.charAt(0) == '&') {
							mailingLists.add(role.substring(1));
						} else if (role.charAt(0) == '^') {
							preReceive.add(role.substring(1));
						} else if (role.charAt(0) == '%') {
							postReceive.add(role.substring(1));
						} else {
							switch (role.charAt(0)) {
							case '#':
								// Permissions
								if (role.equalsIgnoreCase(Constants.ADMIN_ROLE)) {
									team.canAdmin = true;
								} else if (role.equalsIgnoreCase(Constants.FORK_ROLE)) {
									team.canFork = true;
								} else if (role.equalsIgnoreCase(Constants.CREATE_ROLE)) {
									team.canCreate = true;
								}
								break;
							default:
								repositories.add(role);
							}
							repositories.add(role);
						}
					}
					if (!team.canAdmin) {
						// only read permissions for non-admin teams
						team.addRepositoryPermissions(repositories);
					}
					team.addUsers(users);
					team.addMailingLists(mailingLists);
					team.preReceiveScripts.addAll(preReceive);
					team.postReceiveScripts.addAll(postReceive);
					teams.put(team.name.toLowerCase(), team);
				} else {
					// user definition
					String password = roles[0];
					cookies.put(StringUtils.getSHA1(username.toLowerCase() + password), username.toLowerCase());
				}
			}
		}
		return allUsers;
	}

	@Override
	public String toString() {
		return getClass().getSimpleName() + "(" + propertiesFile.getAbsolutePath() + ")";
	}

	/**
	 * Returns the list of all teams available to the login service.
	 * 
	 * @return list of all teams
	 * @since 0.8.0
	 */
	@Override
	public List<String> getAllTeamNames() {
		List<String> list = new ArrayList<String>(teams.keySet());
		Collections.sort(list);
		return list;
	}

	/**
	 * Returns the list of all teams available to the login service.
	 * 
	 * @return list of all teams
	 * @since 0.8.0
	 */
	@Override
	public List<TeamModel> getAllTeams() {
		List<TeamModel> list = new ArrayList<TeamModel>(teams.values());
		list = DeepCopier.copy(list);
		Collections.sort(list);
		return list;
	}

	/**
	 * Returns the list of all teams who are allowed to bypass the access
	 * restriction placed on the specified repository.
	 * 
	 * @param role
	 *            the repository name
	 * @return list of all teamnames that can bypass the access restriction
	 */
	@Override
	public List<String> getTeamnamesForRepositoryRole(String role) {
		List<String> list = new ArrayList<String>();
		try {
			Properties allUsers = read();
			for (String team : allUsers.stringPropertyNames()) {
				if (team.charAt(0) != '@') {
					// skip users
					continue;
				}
				String value = allUsers.getProperty(team);
				String[] values = value.split(",");
				for (int i = 0; i < values.length; i++) {
					String r = values[i];
					if (r.equalsIgnoreCase(role)) {
						// strip leading @
						list.add(team.substring(1));
						break;
					}
				}
			}
		} catch (Throwable t) {
			logger.error(MessageFormat.format("Failed to get teamnames for role {0}!", role), t);
		}
		Collections.sort(list);
		return list;
	}

	/**
	 * Sets the list of all teams who are allowed to bypass the access
	 * restriction placed on the specified repository.
	 * 
	 * @param role
	 *            the repository name
	 * @param teamnames
	 * @return true if successful
	 */
	@Override
	public boolean setTeamnamesForRepositoryRole(String role, List<String> teamnames) {
		try {
			Set<String> specifiedTeams = new HashSet<String>(teamnames);
			Set<String> needsAddRole = new HashSet<String>(specifiedTeams);
			Set<String> needsRemoveRole = new HashSet<String>();

			// identify teams which require add and remove role
			Properties allUsers = read();
			for (String team : allUsers.stringPropertyNames()) {
				if (team.charAt(0) != '@') {
					// skip users
					continue;
				}
				String name = team.substring(1);
				String value = allUsers.getProperty(team);
				String[] values = value.split(",");
				for (int i = 0; i < values.length; i++) {
					String r = values[i];
					if (r.equalsIgnoreCase(role)) {
						// team has role, check against revised team list
						if (specifiedTeams.contains(name)) {
							needsAddRole.remove(name);
						} else {
							// remove role from team
							needsRemoveRole.add(name);
						}
						break;
					}
				}
			}

			// add roles to teams
			for (String name : needsAddRole) {
				String team = "@" + name;
				String teamValues = allUsers.getProperty(team);
				teamValues += "," + role;
				allUsers.put(team, teamValues);
			}

			// remove role from team
			for (String name : needsRemoveRole) {
				String team = "@" + name;
				String[] values = allUsers.getProperty(team).split(",");
				StringBuilder sb = new StringBuilder();
				for (int i = 0; i < values.length; i++) {
					String value = values[i];
					if (!value.equalsIgnoreCase(role)) {
						sb.append(value);
						sb.append(',');
					}
				}
				sb.setLength(sb.length() - 1);

				// update properties
				allUsers.put(team, sb.toString());
			}

			// persist changes
			write(allUsers);
			return true;
		} catch (Throwable t) {
			logger.error(MessageFormat.format("Failed to set teamnames for role {0}!", role), t);
		}
		return false;
	}

	/**
	 * Retrieve the team object for the specified team name.
	 * 
	 * @param teamname
	 * @return a team object or null
	 * @since 0.8.0
	 */
	@Override
	public TeamModel getTeamModel(String teamname) {
		read();
		TeamModel team = teams.get(teamname.toLowerCase());
		if (team != null) {
			// clone the model, otherwise all changes to this object are
			// live and unpersisted
			team = DeepCopier.copy(team);
		}
		return team;
	}

	/**
	 * Updates/writes a complete team object.
	 * 
	 * @param model
	 * @return true if update is successful
	 * @since 0.8.0
	 */
	@Override
	public boolean updateTeamModel(TeamModel model) {
		return updateTeamModel(model.name, model);
	}
	
	/**
	 * Updates/writes all specified team objects.
	 * 
	 * @param models a list of team models
	 * @return true if update is successful
	 * @since 1.2.0
	 */
	public boolean updateTeamModels(Collection<TeamModel> models) {
		try {
			Properties allUsers = read();
			for (TeamModel model : models) {
				updateTeamCache(allUsers, model.name, model);
			}
			write(allUsers);
			return true;
		} catch (Throwable t) {
			logger.error(MessageFormat.format("Failed to update {0} team models!", models.size()), t);
		}
		return false;
	}

	/**
	 * Updates/writes and replaces a complete team object keyed by teamname.
	 * This method allows for renaming a team.
	 * 
	 * @param teamname
	 *            the old teamname
	 * @param model
	 *            the team object to use for teamname
	 * @return true if update is successful
	 * @since 0.8.0
	 */
	@Override
	public boolean updateTeamModel(String teamname, TeamModel model) {
		try {
			Properties allUsers = read();
			updateTeamCache(allUsers, teamname, model);
			write(allUsers);
			return true;
		} catch (Throwable t) {
			logger.error(MessageFormat.format("Failed to update team model {0}!", model.name), t);
		}
		return false;
	}

	private void updateTeamCache(Properties allUsers, String teamname, TeamModel model) {
		StringBuilder sb = new StringBuilder();
		List<String> roles;
		if (model.permissions == null) {
			// legacy, use repository list
			if (model.repositories != null) {
				roles = new ArrayList<String>(model.repositories);
			} else {
				roles = new ArrayList<String>();
			}
		} else {
			// discrete repository permissions
			roles = new ArrayList<String>();
			for (Map.Entry<String, AccessPermission> entry : model.permissions.entrySet()) {
				if (entry.getValue().exceeds(AccessPermission.NONE)) {
					// code:repository (e.g. RW+:~james/myrepo.git
					roles.add(entry.getValue().asRole(entry.getKey()));
				}
			}
		}
		
		// Permissions
		if (model.canAdmin) {
			roles.add(Constants.ADMIN_ROLE);
		}
		if (model.canFork) {
			roles.add(Constants.FORK_ROLE);
		}
		if (model.canCreate) {
			roles.add(Constants.CREATE_ROLE);
		}

		for (String role : roles) {
				sb.append(role);
				sb.append(',');
		}
		
		if (!ArrayUtils.isEmpty(model.users)) {
			for (String user : model.users) {
				sb.append('!');
				sb.append(user);
				sb.append(',');
			}
		}
		if (!ArrayUtils.isEmpty(model.mailingLists)) {
			for (String address : model.mailingLists) {
				sb.append('&');
				sb.append(address);
				sb.append(',');
			}
		}
		if (!ArrayUtils.isEmpty(model.preReceiveScripts)) {
			for (String script : model.preReceiveScripts) {
				sb.append('^');
				sb.append(script);
				sb.append(',');
			}
		}
		if (!ArrayUtils.isEmpty(model.postReceiveScripts)) {
			for (String script : model.postReceiveScripts) {
				sb.append('%');
				sb.append(script);
				sb.append(',');
			}
		}
		// trim trailing comma
		sb.setLength(sb.length() - 1);
		allUsers.remove("@" + teamname);
		allUsers.put("@" + model.name, sb.toString());

		// update team cache
		teams.remove(teamname.toLowerCase());
		teams.put(model.name.toLowerCase(), model);
	}

	/**
	 * Deletes the team object from the user service.
	 * 
	 * @param model
	 * @return true if successful
	 * @since 0.8.0
	 */
	@Override
	public boolean deleteTeamModel(TeamModel model) {
		return deleteTeam(model.name);
	}

	/**
	 * Delete the team object with the specified teamname
	 * 
	 * @param teamname
	 * @return true if successful
	 * @since 0.8.0
	 */
	@Override
	public boolean deleteTeam(String teamname) {
		Properties allUsers = read();
		teams.remove(teamname.toLowerCase());
		allUsers.remove("@" + teamname);
		try {
			write(allUsers);
			return true;
		} catch (Throwable t) {
			logger.error(MessageFormat.format("Failed to delete team {0}!", teamname), t);
		}
		return false;
	}
}
