/**
 * 请勿将俱乐部专享资源复制给其他人，保护知识产权即是保护我们所在的行业，进而保护我们自己的利益
 * 即便是公司的同事，也请尊重 JFinal 作者的努力与付出，不要复制给同事
 * <p>
 * 如果你尚未加入俱乐部，请立即删除该项目，或者现在加入俱乐部：http://jfinal.com/club
 * <p>
 * 俱乐部将提供 jfinal-club 项目文档与设计资源、专用 QQ 群，以及作者在俱乐部定期的分享与答疑，
 * 价值远比仅仅拥有 jfinal club 项目源代码要大得多
 * <p>
 * JFinal 俱乐部是五年以来首次寻求外部资源的尝试，以便于有资源创建更加
 * 高品质的产品与服务，为大家带来更大的价值，所以请大家多多支持，不要将
 * 首次的尝试扼杀在了摇篮之中
 */

package com.jfinal.club.reg;

import com.jfinal.club.common.model.Users;
import com.jfinal.core.Controller;
import com.jfinal.kit.StrKit;
import com.jfinal.validate.Validator;
import com.jfinal.kit.Ret;
import com.jfinal.aop.Inject;
import com.jfinal.club.common.kit.SensitiveWordsKit;
import javafx.scene.control.Skin;
import org.apache.commons.lang3.StringUtils;

import java.util.Map;

/**
 * RegValidator 验证注册表单，并且判断邮箱、昵称是否已被注册
 */
public class RegValidator extends Validator {

    @Inject
    RegService regSrv;

    protected void validate(Controller c) {
        setShortCircuit(true);

        /**
         * 注入 Ret 对象后，验证方法会将验证结果存放于该 Ret 对象中
         * 便于与后面的 controller.renderJson(getRet()) 配合使用
         *
         * Ret.fail() 将设置 state : "fail" 值
         */
        setRet(Ret.fail());
        validateRequired("nickname","msg","用户昵称不能为空");
        validateRequired("phone", "msg", "手机号码不能为空");
        validateString("phone", 1, 11, "msg", "手机号码格式有误");

        String nickname = c.get("nickname");
        if(nickname.length() > 10){
            addError("msg","昵称太长了!");
        }

        if (regSrv.isNickNameExists(c.getPara("phone"))) {
            addError("msg", "昵称已被注册");
        }
        Map<String, String> map = c.getSessionAttr(c.getPara("phone"));
        validateRequired("code", "msg", "手机验证码不能为空");
        if (map != null) {
            if (!c.getPara("code").equals(map.get("SMSCode")) || !c.getPara("phone").equals(map.get("SMSPhone"))) {
                addError("msg", "手机验证码不正确,请重新输入");
            }
        } else {
            addError("msg", "手机验证码不正确,请重新输入");
        }
        validateRequired("pwds", "msg", "密码不能为空");
        validateString("pwds", 6, 100, "msg", "密码长度不能小于6");
        if (!c.getPara("pwds").equals(c.getPara("rpwds"))) {
            addError("msg", "俩次密码输入不正确");
        }
        // 验证码校验放在最后，在 shortCircuit 模式下避免刷新验证码，也即避免重复输入验证码
        validateCaptcha("captcha", "msg", "图片验证码不正确");
        String keepLogin = c.getPara("keepLogin");
        if (!StringUtils.isNotBlank(keepLogin)) {
            addError("msg", "请认真阅读并勾选铁嘴网注册协议");
        }
    }

    protected void handleError(Controller c) {
        // 配合前面的 setRet(Ret) 使用
        c.keepPara("code");
        c.keepModel(Users.class);
        Ret ret = getRet();
        c.renderJson(ret);
    }

    /**
     * TODO 用正则来匹配这些不能使用的字符，而不是用这种 for + contains 这么土的办法
     * 初始化的时候仍然用这个数组，然后用 StringBuilder 来个 for 循环拼成如下的形式：
     * regex = "( |`|~|!|......|\(|\)|=|\[|\]|\?|<|>\。|\,)"
     * 直接在数组中添加转义字符
     * <p>
     * TODO 找时间将所有 nickName 的校验全部封装起来，供 Validattor 与 RegService 中重用，目前先只补下缺失的校验
     * TODO RegService 中的 nickName 校验也要重用同一份代码，以免代码重复
     */
    public static Ret validateNickName(String nickName) {
        if (StrKit.isBlank(nickName)) {
            return Ret.fail("msg", "昵称不能为空");
        }

        // 放开了 _-.  三个字符的限制
        String[] arr = {" ", "`", "~", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "=", "+",
                "[", "]", "{", "}", "\\", "|", ";", ":", "'", "\"", ",", "<", ">", "/", "?",
                "　", "＠", "＃", "＆", "，", "。", "《", "》", "？"};   // 全角字符
        for (String s : arr) {
            if (nickName.contains(s)) {
                return Ret.fail("msg", "昵称不能包含字符: \"" + s + "\"");
            }
        }

        return Ret.ok();
    }
}

