package info.bukova.isspst.services.users;

import info.bukova.isspst.Constants;
import info.bukova.isspst.data.User;
import info.bukova.isspst.security.AuthMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider;
import org.springframework.security.ldap.userdetails.UserDetailsContextMapper;

import java.util.Collection;

/**
 * Mapovač doménových uživatelů Active Directory na uživatele aplikace. Pokud uživatel není v aplikační databází,
 * importu je se tam pomoci {@link LdapUserImporter}. Tento objekt se předává do {@link ActiveDirectoryLdapAuthenticationProvider}.
 * 
 * @author pepa
 *
 */
public class AdUserCtxMapper implements UserDetailsContextMapper {
	
	private UserService userService;
	private RoleService roleService;
	private String allowedGroup;
	
	private final static Logger logger = LoggerFactory.getLogger(AdUserCtxMapper.class);
	
	public AdUserCtxMapper(UserService userService, RoleService roleService) {
		this.userService = userService;
		this.roleService = roleService;
		userService.setAuthMethod(AuthMethod.AD);
	}

	@Override
	public UserDetails mapUserFromContext(DirContextOperations userData,
			String username, Collection<? extends GrantedAuthority> authorities) {
		username = username.toLowerCase();

		try {
			User user = (User) userService.loadUserByUsername(username);
			return user;
		} catch (UsernameNotFoundException e) {
			logger.info("Importing user from Active Directory");
			LdapUserImporter importer = new LdapUserImporter(userService, allowedGroup);
			importer.importUser(username, userData, roleService.getRoleByAuthority(Constants.ROLE_USER));
			
			return userService.loadUserByUsername(username);
		}
	}

	@Override
	public void mapUserToContext(UserDetails user, DirContextAdapter ctx) {
		throw new UnsupportedOperationException("LdapUserDetailsMapper only supports reading from a context. Please" +
                "use a subclass if mapUserToContext() is required.");
	}

	public void setAllowedGroup(String allowedGroup) {
		this.allowedGroup = allowedGroup;
	}

}
