package com.qs.mp.common.utils;

import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.Date;

import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.servlet.http.HttpServletRequest;

import com.qs.mp.common.token.TokenUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.qs.mp.common.exception.NoAuthorizationException;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;

/**
 * 
 * Token生成工具及验证
 * 
 * @author duota
 *
 */
public class TokenUtils {

    private final static Logger logger = LoggerFactory.getLogger(TokenUtils.class);
    
    @Value("${jwt.secret}")
    private static  String secret = "lOi58Jhy6dt";
    // token过期时间天数
    @Value("${jwt.expdays}")
    private static int EXP_DAYS = 30;

    private static Key key = null;

    static {
        SecretKeyFactory keyFactory;
        try {
            keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
            KeySpec keySpec = new PBEKeySpec(secret.toCharArray());
            key = keyFactory.generateSecret(keySpec);

        } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
            logger.error("",e);
        }
    }

    public static String create(TokenUser user) {
        String json = JSON.toJSONString(user);

        return Jwts.builder().setSubject(user.getUserId()).setClaims(JSON.parseObject(json))
                .setExpiration(DateUtils.addDays(new Date(), EXP_DAYS)).signWith(io.jsonwebtoken.SignatureAlgorithm.HS512, key).compact();
    }

    public static TokenUser parse(String compactJws) throws NoAuthorizationException {
        if (compactJws == null) {
            throw new NoAuthorizationException();
        }
        try {
            Jws<Claims> claims = Jwts.parser().setSigningKey(key).parseClaimsJws(compactJws);
            Claims body = claims.getBody();
            JSONObject jsonObject = new JSONObject(body);
            return JSON.toJavaObject(jsonObject, TokenUser.class);
        } catch (Exception e) {
            logger.error("",e);
            throw new NoAuthorizationException();
        }
    }

    public static boolean checkToken(HttpServletRequest request) {
        String token = getToken(request);
        return checkToken(token);
    }

    public static boolean checkToken(String compactJws) {
        try {
            Jwts.parser().setSigningKey(key).parseClaimsJws(compactJws);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public static TokenUser parse(HttpServletRequest request) throws NoAuthorizationException {
        String token = getToken(request);
        return parse(token);
    }

    public static String getToken(HttpServletRequest request) {
        String jwt = request.getHeader("Authorization");
        if (jwt == null) {
            return null;
        }
        jwt = jwt.replace("Bearer", "").trim();

        return jwt;
    }

    public static void main(String[] args) {
        TokenUser user = new TokenUser();
        user.setUserId("E5KH1S648MLVVXH71L1X");
        String jwt = create(user);

        System.out.println("jwt:" + jwt);

        try {
            Thread.sleep(1000);
            System.out.println("checkToken:" + checkToken(jwt));
            TokenUser user2 = parse(jwt);

            System.out.println(JSON.toJSONString(user2));
        } catch (Exception e) {
            e.printStackTrace();
        }

    }



}
