package cn.com.poc.support.security.oauth;

import cn.com.poc.common.constant.FmxParamConfigConstant;
import cn.com.yict.framemax.core.i18n.I18nMessageException;
import cn.com.yict.framemax.frame.service.FmxParamConfigService;
import cn.com.yict.framemax.security.oauth.OauthTokenOperator;
import cn.com.yict.framemax.security.oauth.entity.OauthTokenEntity;
import cn.com.yict.framemax.security.oauth.entity.TokenEntity;
import cn.com.yict.framemax.security.oauth.exception.TokenExpiredException;
import cn.com.yict.framemax.security.oauth.support.OauthTokenOperatorImplementor;
import cn.com.yict.framemax.security.oauth.support.OauthTokenStorage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.Date;

public class MultiDomainOauthTokenOperatorImplementor extends OauthTokenOperatorImplementor implements OauthTokenOperator {

    @Resource
    private OauthTokenStorage tokenStorage;

    @Resource
    private FmxParamConfigService fmxParamConfigService;

    @Override
    public OauthTokenEntity genOauthToken(String user) {
        if (fmxParamConfigService.getConfig(FmxParamConfigConstant.TOKEN_EXPIRED_HOURS) == null) {
            throw new I18nMessageException("exception/login.expiration.time.configured.as.empty");
        }
        super.tokenExpiredHours = Long.valueOf(fmxParamConfigService.getConfig(FmxParamConfigConstant.TOKEN_EXPIRED_HOURS).getParamValue());
        Assert.hasText(user);
        TokenEntity oauthToken = super.newBaseOauthToken(user, null);
        TokenEntity refreshToken = super.newBaseRefreshToken(user);
        oauthToken.setToken1(refreshToken.getToken());
        refreshToken.setToken1(oauthToken.getToken());

        this.tokenStorage.persistToken(oauthToken, refreshToken);
        OauthTokenEntity result = new OauthTokenEntity();
        result.setCreatedOn(oauthToken.getCreatedOn());
        result.setExpiredOn(oauthToken.getExpiredOn());
        result.setUser(oauthToken.getUser());
        result.setOauthToken(oauthToken.getToken());
        result.setRefreshToken(refreshToken.getToken());
        return result;
    }

    @Override
    public OauthTokenEntity refreshOauthToken(String refreshToken) throws TokenExpiredException {
        TokenEntity refreshTokenEntity = this.tokenStorage.readRefreshToken(refreshToken);
        if (refreshTokenEntity == null || StringUtils.isEmpty(refreshTokenEntity.getUser())) {
            throw new TokenExpiredException();
        }
        this.verifyTokenEntity(refreshTokenEntity);
        this.evcitOauthToken(refreshTokenEntity.getToken1());
        TokenEntity oauthTokenEntity = super.newBaseOauthToken(refreshTokenEntity.getUser(), null);

        refreshTokenEntity.setToken1(oauthTokenEntity.getToken());
        oauthTokenEntity.setToken1(refreshTokenEntity.getToken());

        //延长refreshToken过期时间
        long refreshTokenExpiredOn = System.currentTimeMillis() + 1000 * 60 * 60 * super.refreshTokenExpiredHours;
        refreshTokenEntity.setExpiredOn(new Date(refreshTokenExpiredOn));
        this.tokenStorage.persistToken(oauthTokenEntity, refreshTokenEntity);

        OauthTokenEntity result = new OauthTokenEntity();
        result.setCreatedOn(oauthTokenEntity.getCreatedOn());
        result.setExpiredOn(oauthTokenEntity.getExpiredOn());
        result.setUser(oauthTokenEntity.getUser());
        result.setOauthToken(oauthTokenEntity.getToken());
        result.setRefreshToken(refreshToken);
        return result;
    }

    @Override
    public OauthTokenEntity decodeOauthToken(String oauthToken) throws TokenExpiredException {
        if (StringUtils.isEmpty(oauthToken)) {
            throw new TokenExpiredException();
        }
        TokenEntity entity = null;
        if (oauthToken.indexOf('.') > -1) {
            entity = super.decodeBaseOauthToken(oauthToken, true);
            String refreshToken = tokenStorage.getRefreshTokenByOauthToken(entity);
            if (StringUtils.isEmpty(refreshToken)) {
                throw new TokenExpiredException();
            }
            entity.setToken1(refreshToken);
        } else {
            entity = this.tokenStorage.readOauthToken(oauthToken);
            verifyTokenEntity(entity);
        }
        OauthTokenEntity result = new OauthTokenEntity();
        result.setCreatedOn(entity.getCreatedOn());
        result.setExpiredOn(entity.getExpiredOn());
        result.setOauthToken(entity.getToken());
        result.setRefreshToken(entity.getToken1());
        result.setUser(entity.getUser());
        return result;
    }

    @Override
    public void evcitOauthToken(String oauthToken) {
        TokenEntity tokenEntity = super.decodeBaseOauthToken(oauthToken, false);
        this.tokenStorage.evictOauthToken(tokenEntity);
    }

    @Override
    public void evcitRefreshToken(String refreshToken) {
        this.tokenStorage.evictRefreshToken(refreshToken);
    }
}
