package com.philisense.www.api.processor.impl;

import cn.hutool.core.util.NumberUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.philisense.www.api.generator.impl.PuzzleCaptchaGenerator;
import com.philisense.www.api.processor.AbstractVcodeProcessor;
import com.philisense.www.consts.ErrorConst;
import com.philisense.www.consts.VcodeKeys;
import com.philisense.www.dto.PuzzleCaptcha;
import com.philisense.www.enums.VcodeType;
import com.philisense.www.exception.UtilsException;
import com.philisense.www.utils.ImageConvertUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.context.request.ServletWebRequest;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

@Component
public class PuzzleCaptchaProcessor extends AbstractVcodeProcessor<PuzzleCaptcha> {

    @Resource
    private ObjectMapper objectMapper;

    /** 允许的滑块提交位置的误差 */
    private static final int X_OFFSET = 8;
    /** 提交验证的速度限制 */
    private static final int SPEED = 500;

    public PuzzleCaptchaProcessor(PuzzleCaptchaGenerator vcodeGenerator) {
        super(VcodeType.PUZZLE_CAPTCHA, vcodeGenerator);
    }

    @Override
    protected void preValidate(ServletWebRequest request) throws UtilsException {
        String paramX = request.getParameter("x");
        if (StringUtils.isBlank(paramX)) {
            throw new UtilsException("参数x不能为空", ErrorConst.ERR_CODE);
        }
    }

    @Override
    protected void validate(ServletWebRequest request, Object savedValue) throws UtilsException {
        String paramX = request.getParameter("x");
        int paramWidth = ServletRequestUtils.getIntParameter(request.getRequest(), "width", 1);

        Map<String, Object> store = (Map) savedValue;
        int x = (int)store.get(VcodeKeys.PUZZLE_CAPTCHA_X);
        int realWidth = (int)store.get(VcodeKeys.PUZZLE_CAPTCHA_WIDTH);
        long time = (long)store.get(VcodeKeys.PUZZLE_CAPTCHA_TIME);
        long s = System.currentTimeMillis() - time;

        if (s < SPEED) {
            throw new UtilsException("大兄弟这手速！！", ErrorConst.ERR_CODE);
        }
        // 查看前端的缩放比例
        double ratio = NumberUtil.div(realWidth, paramWidth);
        if (Math.abs(x - (Integer.parseInt(paramX) * ratio)) > X_OFFSET * ratio) {
            throw new UtilsException("图片滑块校验失败", ErrorConst.ERR_CODE);
        }
    }

    @Override
    protected Object extractVcodeValueToBeSaved(PuzzleCaptcha puzzleCaptcha) {
        Map<String, Object> genData = new HashMap<>();
        genData.put(VcodeKeys.PUZZLE_CAPTCHA_X, puzzleCaptcha.getX());
        genData.put(VcodeKeys.PUZZLE_CAPTCHA_TIME, System.currentTimeMillis());
        genData.put(VcodeKeys.PUZZLE_CAPTCHA_WIDTH, puzzleCaptcha.getWidth());
        return genData;
    }

    @Override
    protected void send(ServletWebRequest request, PuzzleCaptcha puzzleCaptcha) throws Exception {
        HttpServletResponse response = request.getResponse();
        Map<String, Object> result = new HashMap<>();
        result.put("success", true);
        result.put("message", "生成成功！");
        Map<String, Object> data = new HashMap<>();
        data.put("image1", ImageConvertUtils.toDataUri(puzzleCaptcha.getArtwork(), "png"));
        data.put("image2", ImageConvertUtils.toDataUri(puzzleCaptcha.getVacancy(), "png"));
        data.put("vcodeKey", puzzleCaptcha.getKey());
        result.put("data", data);
        response.getWriter().write(objectMapper.writeValueAsString(result));
    }
}
