package com.cftech.sys.controller;
import com.cftech.core.config.MpGlobalConfig;
import com.cftech.core.jwt.JWTStatus;
import com.cftech.core.sql.Conds;
import com.cftech.sys.model.User;
import com.cftech.sys.security.PermissionSign;
import com.cftech.sys.security.RoleSign;
import com.cftech.sys.service.UserService;
import com.google.code.kaptcha.Producer;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.Assert;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * 用户控制器
 * 
 * @author lisw
 * @since 2016年8月28日 下午3:54:00
 **/
@Controller
@RequestMapping(value = "/page/user")
public class   UserController {


	private static Logger logger = Logger.getLogger(UserController.class);
    @Resource
    private UserService userService;

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private Producer producer;

    public BufferedImage getCaptcha(String uuid) {

        //生成文字验证码
        String code = producer.createText();
        String captchaKey = "CAPTCHA:"+uuid;
        redisTemplate.opsForValue().set(captchaKey, code, 5, TimeUnit.MINUTES);

        return producer.createImage(code);
    }

    public boolean validate(String uuid, String code) {
        String captchaKey = "CAPTCHA:"+uuid;
        if (redisTemplate.hasKey(captchaKey)) {
            String value = redisTemplate.opsForValue().get(captchaKey).toString();
            redisTemplate.delete(captchaKey);
            if (value.equalsIgnoreCase(code)) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }
    /**
     * 验证码
     */
    @GetMapping("captcha.jpg")
    public void captcha(HttpServletRequest request,HttpServletResponse response, String uuid) {

        try {
            Assert.hasText(uuid, "uuid不能为空");
            if(uuid.contains("..")||uuid.contains("/")|| uuid.contains("%00"))
            {
                response.sendError(HttpServletResponse.SC_FORBIDDEN);
                return;
            }

            String refer = request.getHeader("Referer");
            if (com.cftech.core.util.StringUtils.isBlank(refer))
            {
                response.sendError(HttpServletResponse.SC_FORBIDDEN);
                return;
            }
            URL url = new URL(refer);
            String remoteHost = url.getHost();
            if((!MpGlobalConfig.JWT_DOMAIN.equals(remoteHost))||(!refer.contains("/login")))
            {
                response.sendError(HttpServletResponse.SC_FORBIDDEN);
                return;
            }

            response.setHeader("Cache-Control", "no-store, no-cache");
            response.setContentType("image/jpeg");
            //获取图片验证码
            BufferedImage image = getCaptcha(uuid);

            ServletOutputStream out = response.getOutputStream();
            ImageIO.write(image, "jpg", out);
            IOUtils.closeQuietly(out);
        } catch (IOException e) {
            logger.error("验证码失败：" + e.getMessage());
            e.printStackTrace();
        }
    }
    /**
     * 用户登录
     * 
     * @param user
     * @param result
     * @return
     */
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public String login(@Valid User user, BindingResult result, Model model, HttpServletRequest request, String uuid, String code) {
        try {
            //先判断验证码
            boolean captcha = validate(uuid, code);
            if(!captcha){
                model.addAttribute("error", "captcha");
                return "login";
            }
            Subject subject = SecurityUtils.getSubject();
            // 已登陆则 跳到首页
            if (subject.isAuthenticated()) {
                return "redirect:/a/index";
            }
            if (result.hasErrors()) {
                model.addAttribute("error", "参数错误！");
                return "login";
            }
            // 身份验证
            subject.login(new UsernamePasswordToken(user.getUsername(), user.getPassword()));
            // 验证成功在Session中保存用户信息
            Conds conds = new Conds();
            conds.equal("username", user.getUsername());
            conds.equal("delflag", 0);
            conds.equal("state", 0);
            final User authUserInfo = userService.fetchSearchByConds(conds);
            request.getSession().setAttribute("userInfo", authUserInfo);
        } catch (AuthenticationException e) {
        	e.printStackTrace();
            // 身份验证失败
            model.addAttribute("error", "用户名或密码错误 ！");
            return "login";
        }
        return "redirect:/a/index";
    }

    /**
     * 用户登出
     * 
     * @param session
     * @return
     */
    @RequestMapping(value = "/logout", method = RequestMethod.GET)
    public String logout(HttpSession session) {
        session.removeAttribute("userInfo");
        // 登出操作
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return "login";
    }

    /**
     * 基于角色 标识的权限控制案例
     */
    @RequestMapping(value = "/admin")
    @ResponseBody
    @RequiresRoles(value = RoleSign.ADMIN)
    public String admin() {
        return "拥有admin角色,能访问";
    }

    /**
     * 基于权限标识的权限控制案例
     */
    @RequestMapping(value = "/create")
    @ResponseBody
    @RequiresPermissions(value = PermissionSign.USER_EDIT)
    public String create() {
        return "拥有user:create权限,能访问";
    }
    
    
    @RequestMapping(value = "/adduser")
    public void adduser(@Valid User user) {
    	userService.save(user);
    }
    
}
