package com.ejie.u74a.service;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ejie.u74a.model.PerfilUsuario;
import com.ejie.u74a.model.Usuario;
import com.ejie.u74a.model.UsuarioDetalles;
import com.ejie.u74a.util.Constants;

/**
 * Clase encargada de la autenticación del usuario en la aplicación
 * 
 *  
 */
@Service(value = "customUserDetailsService")
public class CustomUserDetailsService implements UserDetailsService {

	private static final Logger logger = LoggerFactory.getLogger(CustomUserDetailsService.class);

	@Autowired()
	private UsuarioService usuarioService;

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.springframework.security.core.userdetails.UserDetailsService# loadUserByUsername(java.lang.String)
	 */
	@Override()
	@Transactional(readOnly = true)
	public UserDetails loadUserByUsername(String ssoId) throws UsernameNotFoundException {
		int codigoUsuario;

		try {
			codigoUsuario = Integer.parseInt(ssoId);
		} catch (NumberFormatException nfe) {
			logger.warn("El código de usuario introducido: '{}' no es un número entero", ssoId);
			throw new UsernameNotFoundException("Usuario no encontrado");
		}

		Usuario usuario = this.usuarioService.findByCodigoUsuario(codigoUsuario);
		logger.debug("Usuario: {}", usuario);

		if (usuario == null) {
			logger.warn("Usuario no encontrado");
			throw new UsernameNotFoundException("Usuario no encontrado");
		}

		UsuarioDetalles usuarioDetalles = new UsuarioDetalles(String.valueOf(usuario.getCodigoUsuario()),
				usuario.getPassword(), getGrantedAuthorities(usuario), usuario.getCodigoOficina(), usuario.getNombre(),
				usuario.getLogin());

		List<String> roles = new ArrayList<String>();

		for (PerfilUsuario perfilUsuario : usuario.getPerfilesUsuario()) {
			roles.add(perfilUsuario.getTipoPerfil());
		}

		if (this.esGestor(roles)) {
			usuarioDetalles.setUrlManual(Constants.MANUAL_GESTOR);
		} else {
			usuarioDetalles.setUrlManual(Constants.MANUAL_USUARIO);
		}

		return usuarioDetalles;
	}

	/**
	 * Obtiene las autorizaciones de acceso del usuario
	 * 
	 * @param usuario Usuario
	 * 
	 * @return lista de autorizaciones
	 */
	private List<GrantedAuthority> getGrantedAuthorities(Usuario usuario) {
		List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();

		for (PerfilUsuario perfilUsuario : usuario.getPerfilesUsuario()) {
			logger.debug("PerfilUsuario: {}", perfilUsuario);
			authorities.add(new SimpleGrantedAuthority("ROLE_" + perfilUsuario.getTipoPerfil()));
		}
		logger.debug("authorities: {}", authorities);
		return authorities;
	}

	/**
	 * Comprueba si el usuario tiene el rol de GESTOR
	 * 
	 * @param roles lista de roles del usuario logado
	 * 
	 * @return true, si tiene el rol de GESTOR
	 */
	private boolean esGestor(List<String> roles) {
		if (roles.contains("GESTOR")) {
			return true;
		}
		return false;
	}
}
