/*
 * Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 

package org.maxkey.web.contorller;

import java.util.regex.Pattern;

import org.maxkey.configuration.EmailConfig;
import org.maxkey.entity.UserInfo;
import org.maxkey.password.onetimepwd.AbstractOtpAuthn;
import org.maxkey.persistence.db.PasswordPolicyValidator;
import org.maxkey.persistence.service.UserInfoService;
import org.maxkey.web.WebConstants;
import org.maxkey.web.WebContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping(value = { "/forgotpassword" })
public class ForgotPasswordContorller {
    private static Logger _logger = LoggerFactory.getLogger(ForgotPasswordContorller.class);

    Pattern emailRegex = Pattern.compile(
            "^\\s*\\w+(?:\\.{0,1}[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$");
    
    Pattern mobileRegex = Pattern.compile(
            "^(13[4,5,6,7,8,9]|15[0,8,9,1,7]|188|187)\\\\d{8}$");
    
    @Autowired
    EmailConfig emailConfig;
    
    public class ForgotType{
        public final static int NOTFOUND = 1;
        public final static int EMAIL = 2;
        public final static int MOBILE = 3;
        public final static int CAPTCHAERROR = 4;
    }
    
    public class PasswordResetResult{
        public final static int SUCCESS = 1;
        public final static int CAPTCHAERROR = 2;
        public final static int PASSWORDERROR = 3;
    }
    
    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    @Qualifier("mailOtpAuthn")
    protected AbstractOtpAuthn mailOtpAuthn;
    
    @Autowired
    @Qualifier("smsOtpAuthn")
    protected AbstractOtpAuthn smsOtpAuthn;
    

    @RequestMapping(value = { "/forward" })
    public ModelAndView forwardreg() {
        _logger.debug("forgotpassword  /forgotpassword/forward.");
        return new ModelAndView("forgotpassword/findpwd");
    }

    @RequestMapping(value = { "/emailmobile" })
    public ModelAndView email(@RequestParam String emailMobile,@RequestParam String captcha) {
        _logger.debug("forgotpassword  /forgotpassword/emailmobile.");
        _logger.debug("emailMobile : " + emailMobile);
        int forgotType = ForgotType.NOTFOUND;
        UserInfo userInfo = null;
        if (captcha != null && captcha
                .equals(WebContext.getSession().getAttribute(
                                WebConstants.KAPTCHA_SESSION_KEY).toString())) {            
            if(mobileRegex.matcher(emailMobile).matches()) {
            	forgotType = ForgotType.MOBILE;
            }else if(emailRegex.matcher(emailMobile).matches()) {
            	forgotType = ForgotType.EMAIL;
            }else {
            	forgotType = ForgotType.EMAIL;
            	emailMobile =emailMobile + "@" + emailConfig.getSmtpHost().substring(emailConfig.getSmtpHost().indexOf(".")+1);
            }
            
            userInfo = userInfoService.queryUserInfoByEmailMobile(emailMobile);
            
            if(null != userInfo) {
	            if (forgotType == ForgotType.EMAIL ) {
	            	mailOtpAuthn.produce(userInfo);
	            }else if (forgotType == ForgotType.MOBILE) {
	            	smsOtpAuthn.produce(userInfo);
	            }
            }
           
        }else {
            _logger.debug("login captcha valid error.");
            forgotType = ForgotType.CAPTCHAERROR;
        }
        
        ModelAndView modelAndView = new ModelAndView("forgotpassword/resetpwd");
        modelAndView.addObject("userId", userInfo==null ?"":userInfo.getId());
        modelAndView.addObject("username", userInfo==null ?"":userInfo.getUsername());
        modelAndView.addObject("emailMobile", emailMobile);
        modelAndView.addObject("forgotType", forgotType);
        
        return modelAndView;
    }

    @RequestMapping(value = { "/setpassword" })
    public ModelAndView setPassWord(
                        @RequestParam String userId, 
                        @RequestParam String username, 
                        @RequestParam int forgotType, 
                        @RequestParam String password,
                        @RequestParam String confirmpassword,
                        @RequestParam String captcha) {
        _logger.debug("forgotPassword  /forgotpassword/pwdreseted.");
        ModelAndView modelAndView = new ModelAndView("forgotpassword/pwdreseted");
        if (null != password && password.equals(confirmpassword)) {
            UserInfo userInfo = new UserInfo();
            userInfo.setId(userId);
            userInfo.setUsername(username);
            userInfo.setPassword(password);
            userInfo.setDecipherable(password);
            if ((forgotType == ForgotType.EMAIL && mailOtpAuthn.validate(userInfo, captcha)) ||
                    (forgotType == ForgotType.MOBILE && smsOtpAuthn.validate(userInfo, captcha))
                ) {
                if(userInfoService.changePassword(userInfo,true)) {
                	modelAndView.addObject("passwordResetResult", PasswordResetResult.SUCCESS);
                }else {
                	;
                	modelAndView.addObject("validate_result", WebContext.getAttribute(PasswordPolicyValidator.PASSWORD_POLICY_VALIDATE_RESULT));
                	modelAndView.addObject("passwordResetResult", PasswordResetResult.PASSWORDERROR);
                }
            } else {
                modelAndView.addObject("passwordResetResult", PasswordResetResult.CAPTCHAERROR);
            }
        } else {
            modelAndView.addObject("passwordResetResult", PasswordResetResult.PASSWORDERROR);
        }
        return modelAndView;
    }
}
