package com.leanwo.activiti.service.base.impl;

import java.util.Date;
import java.util.UUID;

import javax.inject.Inject;
import javax.inject.Named;

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

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.InvalidClaimException;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.leanwo.activiti.config.TokenConfiguration;
import com.leanwo.activiti.exception.AuthorizeException;
import com.leanwo.activiti.exception.TokenException;
import com.leanwo.activiti.service.base.TokenService;
import com.leanwo.activiti.util.LoginContext;
import com.leanwo.activiti.util.LoginContextUtil;
import com.leanwo.activiti.util.TokenUtil;


// TODO: Auto-generated Javadoc
/**
 * The Class TokenServiceImpl.
 */
@Named
public class TokenServiceImpl implements TokenService {

	/** The Constant logger. */
	private final static Logger logger = LoggerFactory.getLogger(TokenServiceImpl.class.getName());

    /** The Token algorithm. */
    // Token 加密算法
    @Inject
    private Algorithm algorithm;

    /** The Token JWT verifier. */
    // Token 验证器
    @Inject
    private JWTVerifier jWTVerifier;

    @Inject
    private TokenConfiguration tokenConfiguration;
    
	
	/**
	 * Parses the login context.
	 *
	 * @param token the token
	 */
	@Override
	public void parseLoginContext(String token, Long accountId) {
		TokenUtil.clear();
		LoginContextUtil.clear();
		
		DecodedJWT jwt = null;
		try {
			jwt = jWTVerifier.verify(token);
		} catch (JWTDecodeException | InvalidClaimException exception) {
			logger.debug("token校验失败。", exception);
			throw new AuthorizeException("无权限访问数据。");
		} catch (TokenExpiredException exception) {
			logger.debug("Token过期。", exception.getMessage());
			throw new AuthorizeException("登录超时。");
		}
		LoginContext loginContext = new LoginContext();
		Claim claim = jwt.getClaim("accountId");
		String accountIdInTokenStr = claim.asString();
		if(accountIdInTokenStr != null) {
			Long accountIdInToken = Long.parseLong(accountIdInTokenStr);
			if(!accountIdInToken.equals(accountId)) {
				throw new AuthorizeException("权限异常，请求头的账套Id与JWT解密账号Id不相同");
			}
			loginContext.setAccountId(accountIdInToken);			
		}else {
			loginContext.setAccountId(accountId);
		}
		
		String userId = jwt.getSubject();
		if(userId != null) {
			loginContext.setUserId(Long.parseLong(userId));
		}

		TokenUtil.setToken(token);

		LoginContextUtil.setLoginContext(loginContext);
	}
	
	/* (non-Javadoc)
     * @see com.leanwo.prodog.service.system.TokenService#generateRegisterToken()
     */
    @Override
    public String generateTempToken() {
        long currentMs = new Date().getTime();
        Date expireDate = new Date(currentMs + tokenConfiguration.getTokenInvalidSecond()*1000L);
        String tokenString = null;
        // Create and Sign a Token
        try {
            tokenString = JWT.create().withIssuer(tokenConfiguration.getTokenIssuer()) // 签发者
                .withExpiresAt(expireDate) // 过期时间
                .withIssuedAt(new Date()) // 签发时间
                // .withNotBefore(notBeforeDate) // 下次可访问的时间
                .withClaim("uuid", UUID.randomUUID().toString()).sign(algorithm);
        } catch (JWTCreationException exception) {
            logger.error("JWT Token生成失败.", exception);
            throw new TokenException("JWT Token生成失败.");
        }
        return tokenString;
    }
}
