package com.ejie.ab79.rest.configuracion;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.web.filter.OncePerRequestFilter;

import com.ejie.ab79.comun.Constantes;
import com.ejie.ab79.model.REST.servicioWeb.GenericResponse;
import com.ejie.ab79.rest.util.AuthenticationUtil;
import com.fasterxml.jackson.databind.ObjectMapper;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
/**
 * Filtro para autorizar peticiones a recursos protegidos de nuestro API.
 *  
 *
 */
public class JWTAuthorizationFilter extends OncePerRequestFilter {

	private static final String HEADER_AUTHORIZACION_KEY = "Authorization";
	private static final String TOKEN_BEARER_PREFIX = "Bearer ";
	private static final String SUPER_SECRET_KEY = "ab79BM";

	/**
	 * constructor
	 */
	public JWTAuthorizationFilter() {
		super();
	}
	
	
	/**
	 *  Proceso para autorizar peticiones a recursos protegidos de nuestro API.
	 *  Filtro que es capaz de interceptar las invocaciones a recursos protegidos 
	 *  para recuperar el token y determinar si el cliente tiene permisos o no
	 */
	
	@Override
	protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
			throws IOException, ServletException {
		
		String header = req.getHeader(HEADER_AUTHORIZACION_KEY);
		if (header == null || !header.startsWith(TOKEN_BEARER_PREFIX)) {
			if (req.getServletPath().equalsIgnoreCase("/user/login")
					|| req.getMethod().equals("OPTIONS")){
		
				chain.doFilter(req, res);
				
			}else{
				 res.setContentType(Constantes.APPLICATION_JSON_UTF8_VALUE);
			        res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
			          
			        String jsonString = new ObjectMapper().writeValueAsString(
		        		new GenericResponse(Constantes.ENVIO_JSON_ESTADO_ERROR, "error.acceso", "Acceso denegado", "Sarrera dekekatuta")
			        );
			        res.getWriter().print(jsonString);	
				}
			return;
		}
		try{
			getAuthentication(req);
			chain.doFilter(req, res);
		}catch (Exception e) {
	        res.setContentType(Constantes.APPLICATION_JSON_UTF8_VALUE);
	        res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
	          
	        String jsonString = new ObjectMapper().writeValueAsString(
        		new GenericResponse(Constantes.ENVIO_JSON_ESTADO_ERROR, "error.acceso", "Acceso denegado", "Sarrera dekekatuta")
	        );
	        res.getWriter().print(jsonString);
	        
	        return;
		}
	}

	private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
		String token = request.getHeader(HEADER_AUTHORIZACION_KEY);
		if (token != null) {
			
			Claims claims = validateToken(request);
			// Se procesa el token y se recupera el usuario.
			String user=claims.getSubject();
			Integer id=Integer.valueOf(claims.getId());
			if (user != null) {

				AuthenticationUtil.addAuthentication(id, user, "N/A", "N/A", "ROLE_USER");
				
				return null;
			}
			return null;
		}
		return null;
	}
	
	private Claims validateToken(HttpServletRequest request) {
		String jwtToken = request.getHeader(HEADER_AUTHORIZACION_KEY).replace(TOKEN_BEARER_PREFIX, "");
		return Jwts.parser().setSigningKey(SUPER_SECRET_KEY.getBytes()).parseClaimsJws(jwtToken).getBody();
	}
}