package com.apobates.forum.thrones.admin.controller.helper;

import com.apobates.forum.member.storage.OnlineMemberStorage;
import com.apobates.forum.member.storage.core.MemberSessionBean;
import com.apobates.forum.member.storage.core.MemberSessionBeanBuilder;
import com.apobates.forum.thrones.admin.exception.ResourceNotFoundException;
import com.apobates.forum.utils.Commons;
import com.apobates.forum.utils.TipMessage;
import com.apobates.forum.utils.TipMessageLevelEnum;
import com.apobates.forum.utils.lang.ReplicableException;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.NoHandlerFoundException;

/**
 *
 * @author xiaofanku
 * @since 20200604
 */
@ControllerAdvice
public class AdminControllerAdvice {
    @Autowired
    private OnlineMemberStorage onlineMemberStorage;
    @Value("${site.domain}")
    private String siteDomain;
    private final static Logger logger = LoggerFactory.getLogger(AdminControllerAdvice.class);
    
    @ModelAttribute
    public MemberSessionBean getSessionBean(HttpServletRequest request) {
        logger.info("[ADM][CCA]EXE Sequence: 2");
        MemberSessionBean mbean = onlineMemberStorage.getInstance(request, "AdminControllerAdvice").orElse(null);
        if (null == mbean) {
            mbean = MemberSessionBeanBuilder.empty().build(Commons.getRequestIp(request), "AdminControllerAdvice");
        }
        return mbean;
    }
    
    //https://stackoverflow.com/questions/24498662/howto-handle-404-exceptions-globally-using-spring-mvc-configured-using-java-base
    //https://stackoverflow.com/questions/2066946/trigger-404-in-spring-mvc-controller
    @ExceptionHandler(value={ResourceNotFoundException.class, NoHandlerFoundException.class, ReplicableException.class})
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ModelAndView getModuleVisitException(
            HttpServletRequest request, 
            HttpServletResponse response, 
            Exception e){
        if(logger.isDebugEnabled()){
            logger.debug(e.getMessage());
        }
        e.printStackTrace();
        return normal(e, e.getMessage(), request, response, "404");
    }
    @ExceptionHandler(value={
            java.lang.NoClassDefFoundError.class,
            org.eclipse.persistence.exceptions.DatabaseException.class, 
            javax.persistence.RollbackException.class})
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ModelAndView getJpaDBExecteException(
            HttpServletRequest request, 
            HttpServletResponse response, 
            Exception e){
        if(logger.isDebugEnabled()){
            logger.debug(e.getMessage());
        }
        e.printStackTrace();
        return normal(e, "服务器组件发生错误", request, response, "500");
    }
    private ModelAndView normal(
            Exception e, 
            String message, 
            HttpServletRequest request, 
            HttpServletResponse response, 
            String viewName){
        if(isAjaxRequest(request)){
            TipMessage tipMsg = new TipMessage(message, TipMessageLevelEnum.ERR.getLevel(), request.getRequestURL().toString());
            try {
                PrintWriter writer = response.getWriter();
                writer.write(tipMsg.toJsonString());
                writer.flush();
            } catch (IOException ex) {
                if(logger.isDebugEnabled()){
                    logger.debug("["+viewName+"]输出JSON格式消息", ex);
                }
            }
            return null;
        }
        ModelAndView model=new ModelAndView();
        model.addObject("errors", message);
        model.addObject("url", request.getRequestURL());
        model.addObject("referer", request.getHeader("referer"));
        model.addObject("paramer", request.getParameterMap());
        model.addObject("exception", e);
        model.addObject("debug", logger.isDebugEnabled());
        model.addObject("BASE", siteDomain); //request.getContextPath()
        model.setViewName(viewName);
        return model;
    }
    private boolean isAjaxRequest(HttpServletRequest request){
          return ((request.getHeader("accept").contains("application/json") || (request.getHeader("X-Requested-With") != null 
                  && 
               request.getHeader("X-Requested-With").contains("XMLHttpRequest"))));
    }
}