package com.yeejoin.amos.speech;

import com.alibaba.nls.client.AccessToken;
import com.alibaba.nls.client.protocol.NlsClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;


/**
 * 阿里云nlsClient语音识别客户端
 * 应用全局创建一个NlsClient实例，默认服务地址为阿里云线上服务地址,默认值：wss://nls-gateway.cn-shanghai.aliyuncs.com/ws/v1
 */
public class AppNslClient {
    private static final Logger logger = LoggerFactory.getLogger(AppNslClientToken.class);
    private volatile static NlsClient nlsClient;

    private AppNslClient() {
    }

    public static NlsClient instance() {
        if (nlsClient == null) {
            synchronized (NlsClient.class) {
                if (nlsClient == null) {
                    logger.warn("AppNslClient语音识别客户端为空，开始创建...");
                    nlsClient = new NlsClient(AppNslClientToken.instance().getToken());
                    return nlsClient;
                }
            }
        }
        //设置访问token
        nlsClient.setToken(AppNslClientToken.instance().getToken());
        return nlsClient;
    }

}

/**
 * AppNslClientToken
 */
class AppNslClientToken {
    private static final Logger logger = LoggerFactory.getLogger(AppNslClientToken.class);
    private volatile static AccessToken accessToken;
    private static long getTokenTime;

    private AppNslClientToken() {
    }

    public static AccessToken instance() {
        if (accessToken == null) {
            synchronized (NlsClient.class) {
                if (accessToken == null) {
                    logger.warn("token为空，开始获取token...");
                    accessToken = getAccessToken();
                    getTokenTime = System.currentTimeMillis();
                }
            }
        }
        //token过期自更新
        //显示18天过期，实测两天就失效了
        /*if (getTokenTime + accessToken.getExpireTime() <= System.currentTimeMillis()) {
            logger.warn("token已过期，开始重新获取...");
            accessToken = getAccessToken();
            getTokenTime = System.currentTimeMillis();
        } else {
            long time = getTokenTime + accessToken.getExpireTime() - System.currentTimeMillis();
            logger.warn("token过期还剩：" + "(" + time / (1000 * 60 * 60 * 24) + "天)");
        }*/
        //一天更新一次
        if (System.currentTimeMillis() - getTokenTime > (1000 * 60 * 60)) {
            logger.warn("token已过期，开始重新获取...");
            accessToken = getAccessToken();
            getTokenTime = System.currentTimeMillis();
        } else {
            long time = System.currentTimeMillis() - getTokenTime;
            logger.warn("token过期还剩：" + "(" + time / (1000 * 60 * 60 * 24) + "天)");
        }
        return accessToken;
    }

    /**
     * 获取访问Token,包含token和过期时间（2021-11-30测试Token过期时间为18天）
     * 避免多次获取可能导致已进行的任务token失效
     * @return token 访问token
     */
    private static AccessToken getAccessToken() {
        AccessToken accessToken = new AccessToken(SpeechConfig.AccessKeyId, SpeechConfig.AccessKeySecret);
        try {
            accessToken.apply();
            logger.warn("获取到最新的token: " + accessToken.getToken() + ", 过期时间: " + accessToken.getExpireTime() + "(" + accessToken.getExpireTime() / (1000 * 60 * 60 * 24) + "天)");
            return accessToken;
        } catch (IOException e) {
            logger.error("获取语音识别客户端token失败！原因：" + e.getMessage());
            throw new RuntimeException("获取语音识别客户端token失败！原因：" + e.getMessage());
        }
    }
}
