/*
 * Copyright 2013 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.manager;

import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gitblit.ConfigUserService;
import com.gitblit.Constants;
import com.gitblit.IStoredSettings;
import com.gitblit.IUserService;
import com.gitblit.Keys;
import com.gitblit.extensions.UserTeamLifeCycleListener;
import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.StringUtils;

/**
 * The user manager manages persistence and retrieval of users and teams.
 *
 * @author James Moger
 *
 */
public class UserManager implements IUserManager {

	private final Logger logger = LoggerFactory.getLogger(getClass());

	private final IStoredSettings settings;

	private final IRuntimeManager runtimeManager;

	private final IPluginManager pluginManager;

	private final Map<String, String> legacyBackingServices;

	private IUserService userService;

	public UserManager(IRuntimeManager runtimeManager, IPluginManager pluginManager) {
		this.settings = runtimeManager.getSettings();
		this.runtimeManager = runtimeManager;
		this.pluginManager = pluginManager;

		// map of legacy realm backing user services
		legacyBackingServices = new HashMap<String, String>();
		legacyBackingServices.put("com.gitblit.HtpasswdUserService", "realm.htpasswd.backingUserService");
		legacyBackingServices.put("com.gitblit.LdapUserService", "realm.ldap.backingUserService");
		legacyBackingServices.put("com.gitblit.PAMUserService", "realm.pam.backingUserService");
		legacyBackingServices.put("com.gitblit.RedmineUserService", "realm.redmine.backingUserService");
		legacyBackingServices.put("com.gitblit.SalesforceUserService", "realm.salesforce.backingUserService");
		legacyBackingServices.put("com.gitblit.WindowsUserService", "realm.windows.backingUserService");
	}

	/**
	 * Set the user service. The user service authenticates *local* users and is
	 * responsible for persisting and retrieving all users and all teams.
	 *
	 * @param userService
	 */
	public void setUserService(IUserService userService) {
		logger.info(userService.toString());
		this.userService = userService;
		this.userService.setup(runtimeManager);
	}

	@Override
	public void setup(IRuntimeManager runtimeManager) {
		// NOOP
	}

	@Override
	public UserManager start() {
		if (this.userService == null) {
			String realm = settings.getString(Keys.realm.userService, "${baseFolder}/users.conf");
			IUserService service = null;
			if (legacyBackingServices.containsKey(realm)) {
				// create the user service from the legacy config
				String realmKey = legacyBackingServices.get(realm);
				logger.warn("");
				logger.warn(Constants.BORDER2);
				logger.warn(" Key '{}' is obsolete!", realmKey);
				logger.warn(" Please set '{}={}'", Keys.realm.userService, settings.getString(realmKey, "${baseFolder}/users.conf"));
				logger.warn(Constants.BORDER2);
				logger.warn("");
				File realmFile = runtimeManager.getFileOrFolder(realmKey, "${baseFolder}/users.conf");
				service = createUserService(realmFile);
			} else {
				// either a file path OR a custom user service
				try {
					// check to see if this "file" is a custom user service class
					Class<?> realmClass = Class.forName(realm);
					service = (IUserService) realmClass.newInstance();
				} catch (Throwable t) {
					// typical file path configuration
					File realmFile = runtimeManager.getFileOrFolder(Keys.realm.userService, "${baseFolder}/users.conf");
					service = createUserService(realmFile);
				}
			}
			setUserService(service);
		}
		return this;
	}

	protected IUserService createUserService(File realmFile) {
		IUserService service = null;
		if (realmFile.getName().toLowerCase().endsWith(".conf")) {
			// config-based realm file
			service = new ConfigUserService(realmFile);
		}

		assert service != null;

		if (!realmFile.exists()) {
			// Create the Administrator account for a new realm file
			try {
				realmFile.createNewFile();
			} catch (IOException x) {
				logger.error(MessageFormat.format("COULD NOT CREATE REALM FILE {0}!", realmFile), x);
			}
			UserModel admin = new UserModel("admin");
			admin.password = "admin";
			admin.canAdmin = true;
			admin.excludeFromFederation = true;
			service.updateUserModel(admin);
		}

		return service;
	}

	@Override
	public UserManager stop() {
		return this;
	}

	/**
	 * Returns true if the username represents an internal account
	 *
	 * @param username
	 * @return true if the specified username represents an internal account
	 */
	@Override
	public boolean isInternalAccount(String username) {
		return !StringUtils.isEmpty(username)
				&& (username.equalsIgnoreCase(Constants.FEDERATION_USER)
						|| username.equalsIgnoreCase(UserModel.ANONYMOUS.username));
	}

	/**
	 * Returns the cookie value for the specified user.
	 *
	 * @param model
	 * @return cookie value
	 */
	@Override
	public String getCookie(UserModel model) {
		return userService.getCookie(model);
	}

	/**
	 * Retrieve the user object for the specified cookie.
	 *
	 * @param cookie
	 * @return a user object or null
	 */
	@Override
	public UserModel getUserModel(char[] cookie) {
		UserModel user = userService.getUserModel(cookie);
		return user;
	}

	/**
	 * Retrieve the user object for the specified username.
	 *
	 * @param username
	 * @return a user object or null
	 */
	@Override
	public UserModel getUserModel(String username) {
		if (StringUtils.isEmpty(username)) {
			return null;
		}
		String usernameDecoded = StringUtils.decodeUsername(username);
		UserModel user = userService.getUserModel(usernameDecoded);
		return user;
	}

	/**
	 * Updates/writes a complete user object.
	 *
	 * @param model
	 * @return true if update is successful
	 */
	@Override
	public boolean updateUserModel(UserModel model) {
		final boolean isCreate = null == userService.getUserModel(model.username);
		if (userService.updateUserModel(model)) {
			if (isCreate) {
				callCreateUserListeners(model);
			}
			return true;
		}
		return false;
	}

	/**
	 * 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) {
		return userService.updateUserModels(models);
	}

	/**
	 * Adds/updates a 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) {
		final boolean isCreate = null == userService.getUserModel(username);
		if (userService.updateUserModel(username, model)) {
			if (isCreate) {
				callCreateUserListeners(model);
			}
			return true;
		}
		return false;
	}

	/**
	 * Deletes the user object from the user service.
	 *
	 * @param model
	 * @return true if successful
	 */
	@Override
	public boolean deleteUserModel(UserModel model) {
		if (userService.deleteUserModel(model)) {
			callDeleteUserListeners(model);
			return true;
		}
		return false;
	}

	/**
	 * Delete the user object with the specified username
	 *
	 * @param username
	 * @return true if successful
	 */
	@Override
	public boolean deleteUser(String username) {
		if (StringUtils.isEmpty(username)) {
			return false;
		}
		String usernameDecoded = StringUtils.decodeUsername(username);
		UserModel user = getUserModel(usernameDecoded);
		if (userService.deleteUser(usernameDecoded)) {
			callDeleteUserListeners(user);
			return true;
		}
		return false;
	}

	/**
	 * Returns the list of all users available to the login service.
	 *
	 * @return list of all usernames
	 */
	@Override
	public List<String> getAllUsernames() {
		List<String> names = new ArrayList<String>(userService.getAllUsernames());
		return names;
	}

	/**
	 * Returns the list of all users available to the login service.
	 *
	 * @return list of all users
	 * @since 0.8.0
	 */
	@Override
	public List<UserModel> getAllUsers() {
		List<UserModel> users = userService.getAllUsers();
		return users;
	}

	/**
	 * 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> teams = userService.getAllTeamNames();
		return teams;
	}

	/**
	 * 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> teams = userService.getAllTeams();
		return teams;
	}

	/**
	 * 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 teams that can bypass the access restriction
	 * @since 0.8.0
	 */
	@Override
	public List<String> getTeamNamesForRepositoryRole(String role) {
		List<String> teams = userService.getTeamNamesForRepositoryRole(role);
		return teams;
	}

	/**
	 * 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) {
		TeamModel team = userService.getTeamModel(teamname);
		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) {
		final boolean isCreate = null == userService.getTeamModel(model.name);
		if (userService.updateTeamModel(model)) {
			if (isCreate) {
				callCreateTeamListeners(model);
			}
			return true;
		}
		return false;
	}

	/**
	 * Updates/writes all specified team objects.
	 *
	 * @param models a list of team models
	 * @return true if update is successful
	 * @since 1.2.0
	 */
	@Override
	public boolean updateTeamModels(Collection<TeamModel> models) {
		return userService.updateTeamModels(models);
	}

	/**
	 * 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) {
		final boolean isCreate = null == userService.getTeamModel(teamname);
		if (userService.updateTeamModel(teamname, model)) {
			if (isCreate) {
				callCreateTeamListeners(model);
			}
			return true;
		}
		return false;
	}

	/**
	 * Deletes the team object from the user service.
	 *
	 * @param model
	 * @return true if successful
	 * @since 0.8.0
	 */
	@Override
	public boolean deleteTeamModel(TeamModel model) {
		if (userService.deleteTeamModel(model)) {
			callDeleteTeamListeners(model);
			return true;
		}
		return false;
	}

	/**
	 * Delete the team object with the specified teamname
	 *
	 * @param teamname
	 * @return true if successful
	 * @since 0.8.0
	 */
	@Override
	public boolean deleteTeam(String teamname) {
		TeamModel team = userService.getTeamModel(teamname);
		if (userService.deleteTeam(teamname)) {
			callDeleteTeamListeners(team);
			return true;
		}
		return false;
	}

	/**
	 * 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
	 * @since 0.8.0
	 */
	@Override
	public List<String> getUsernamesForRepositoryRole(String role) {
		return userService.getUsernamesForRepositoryRole(role);
	}

	/**
	 * Renames a repository role.
	 *
	 * @param oldRole
	 * @param newRole
	 * @return true if successful
	 */
	@Override
	public boolean renameRepositoryRole(String oldRole, String newRole) {
		return userService.renameRepositoryRole(oldRole, newRole);
	}

	/**
	 * Removes a repository role from all users.
	 *
	 * @param role
	 * @return true if successful
	 */
	@Override
	public boolean deleteRepositoryRole(String role) {
		return userService.deleteRepositoryRole(role);
	}

	protected void callCreateUserListeners(UserModel user) {
		if (pluginManager == null || user == null) {
			return;
		}

		for (UserTeamLifeCycleListener listener : pluginManager.getExtensions(UserTeamLifeCycleListener.class)) {
			try {
				listener.onCreation(user);
			} catch (Throwable t) {
				logger.error(String.format("failed to call plugin.onCreation%s", user.username), t);
			}
		}
	}

	protected void callCreateTeamListeners(TeamModel team) {
		if (pluginManager == null || team == null) {
			return;
		}

		for (UserTeamLifeCycleListener listener : pluginManager.getExtensions(UserTeamLifeCycleListener.class)) {
			try {
				listener.onCreation(team);
			} catch (Throwable t) {
				logger.error(String.format("failed to call plugin.onCreation %s", team.name), t);
			}
		}
	}

	protected void callDeleteUserListeners(UserModel user) {
		if (pluginManager == null || user == null) {
			return;
		}

		for (UserTeamLifeCycleListener listener : pluginManager.getExtensions(UserTeamLifeCycleListener.class)) {
			try {
				listener.onDeletion(user);
			} catch (Throwable t) {
				logger.error(String.format("failed to call plugin.onDeletion %s", user.username), t);
			}
		}
	}

	protected void callDeleteTeamListeners(TeamModel team) {
		if (pluginManager == null || team == null) {
			return;
		}

		for (UserTeamLifeCycleListener listener : pluginManager.getExtensions(UserTeamLifeCycleListener.class)) {
			try {
				listener.onDeletion(team);
			} catch (Throwable t) {
				logger.error(String.format("failed to call plugin.onDeletion %s", team.name), t);
			}
		}
	}
}
