package xyz.wbsite.action;

import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import xyz.wbsite.frame.base.LocalData;
import xyz.wbsite.frame.listener.FrameListener;
import xyz.wbsite.frame.utils.LogUtil;
import xyz.wbsite.frame.utils.RequestUtil;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collections;
import java.util.Map;

/**
 * 全局错误处理器，任何未处理异常都会进入
 *
 * @author author
 * @version 0.0.1
 * @since 2017-01-01
 */
@Controller
public class GlobalErrorController extends BasicErrorController {

    public GlobalErrorController() {
        super(new DefaultErrorAttributes(), new ErrorProperties());
    }

    @Override
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
        return super.error(request);
    }

    @Override
    @RequestMapping(produces = "text/html")
    public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
        HttpStatus status = this.getStatus(request);
        Map<String, Object> model = Collections.unmodifiableMap(this.getErrorAttributes(request, true));
        response.setStatus(status.value());
        ModelAndView modelAndView = this.resolveErrorView(request, response, status, model);
        if (modelAndView == null) {
            modelAndView = new ModelAndView("error", model);
        }
        switch (status) {
            case FORBIDDEN://403
                String errorUrl = RequestUtil.getErrorUrl(request);
                errorUrl = errorUrl.replaceFirst(LocalData.getContext(), "");
                String indexPage = LocalData.getEnvironment().getProperty("web.url.index", "/index.htm");
                String loginPage = LocalData.getEnvironment().getProperty("web.url.login", "/login.htm");
                if ((errorUrl.equals(indexPage) || errorUrl.equals("/")) && LocalData.getToken() == null) {
                    RequestUtil.setRedirect(loginPage);
                } else {
                    modelAndView.setViewName("403");
                }
                break;
            case NOT_FOUND://404
                modelAndView.setViewName("404");
                break;
            case INTERNAL_SERVER_ERROR://500
            default:
                try {
                    FrameListener instance = FrameListener.getInstance();
                    instance.onError((String) model.get("trace"));
                    modelAndView.setViewName("500");
                } catch (Exception ex) {
                    LogUtil.dumpException(ex);
                } finally {
                    modelAndView.setViewName("500");
                }
                break;
        }

        return modelAndView;
    }
}
