package cn.quantgroup.xyqb.config.captcha;

import cn.quantgroup.xyqb.thirdparty.jcaptcha.AbstractManageableImageCaptchaService;
import com.octo.captcha.Captcha;
import com.octo.captcha.engine.CaptchaEngine;
import com.octo.captcha.service.CaptchaServiceException;
import com.octo.captcha.service.captchastore.CaptchaStore;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.Locale;

/**
 * 类名称：CustomCaptchaService
 * 类描述：自定义的验证马实现服务
 *
 * @author 李宁
 * @version 1.0.0
 * 创建时间：15/11/17 19:41
 * 修改人：
 * 修改时间：15/11/17 19:41
 * 修改备注：
 */
@Slf4j
public class CustomCaptchaService extends AbstractManageableImageCaptchaService {

    /*
    * 验证码管理策略:
    * 1, 生成验证码时, 会进行配额检查, 当达到配额时, 进行垃圾验证码清理
    * 2, 一个验证码校验完成后, 不管成功失败, 都会直接失效, 删除?
    * */
    private static final Integer MIN_GUARANTED_STORAGE_DELAY_IN_SECONDS = 120;         // 默认值, 执行垃圾清理时, 存活超过180s的验证码都会被清除
    private static final Integer MAX_CAPTCHA_STORE_SIZE = 70000;                    // 最大容量, 默认值是10w
    private static final Integer CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION = 52500; // 配额, 超过此配额时执行一次垃圾清除, 默认值是:75000

    public CustomCaptchaService(CaptchaStore captchaStore, CaptchaEngine captchaEngine) {
        this(captchaStore, captchaEngine, MIN_GUARANTED_STORAGE_DELAY_IN_SECONDS, MAX_CAPTCHA_STORE_SIZE, CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION);
    }


    protected CustomCaptchaService(CaptchaStore captchaStore, CaptchaEngine captchaEngine, int minGuarantedStorageDelayInSeconds, int maxCaptchaStoreSize, int captchaStoreLoadBeforeGarbageCollection) {
        super(captchaStore, captchaEngine, minGuarantedStorageDelayInSeconds, maxCaptchaStoreSize, captchaStoreLoadBeforeGarbageCollection);
    }

    @Override
    public long getCustomStoreSize() {
        return this.store.getSize();
    }

    /**
     * 重写校验, 需要将原来的 key 失效
     *
     * @param id
     * @param response
     * @return
     * @throws CaptchaServiceException
     */
    @Override
    public Boolean validateResponseForID(String id, Object response) throws CaptchaServiceException {
        if (StringUtils.isBlank(id)) {
            return false;
        }
        boolean valid;
        try {
            Captcha captcha = this.store.getCaptcha(id);
            if (null == captcha || captcha.hasGetChalengeBeenCalled()) {
                return false;
            }
            valid = captcha.validateResponse(response);
        } catch (Exception ex) {
            log.warn("can not get captcha from redis");
            valid = false;
        }

        this.getTimes().remove(id);
        if (valid) {
            addNumberOfCorrectResponse(1);
        } else {
            addNumberOfUncorrectResponse(1);
        }

        return valid;
    }

    /**
     * 请求新的图形验证码
     *
     * @param ID
     * @param locale
     * @return
     * @throws CaptchaServiceException
     */
    @Override
    public Object getChallengeForID(String ID, Locale locale) throws CaptchaServiceException {
        Captcha captcha = this.generateAndStoreCaptcha(locale, ID);
        Object challenge = this.getChallengeClone(captcha);
        captcha.disposeChallenge();
        return challenge;
    }

    @Override
    public void garbageCollectCaptchaStore() {
        super.garbageCollectCaptchaStore();
    }

}
