package cn.wisenergy.web.admin.controller.common;

import cn.wisenergy.common.utils.exception.BASE_RESP_CODE_ENUM;
import cn.wisenergy.common.utils.exception.BaseCustomException;
import cn.wisenergy.common.utils.exception.Result;
import cn.wisenergy.web.admin.utils.CustomException;
import cn.wisenergy.web.admin.utils.RESP_CODE_ENUM;
import net.sf.json.JSONObject;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;

/**
 * 控制器基类
 *
 * @author wyy
 * @date 2019年08月15日
 */
public abstract class BaseController {
    private static final long serialVersionUID = -6344078923170236539L;
    protected Logger log = LoggerFactory.getLogger(this.getClass());


    /**
     * 应用接口异常处理
     *
     * @param response Response相应对象
     * @param ex
     */
    @ResponseBody
    @ExceptionHandler(Exception.class)
    public void handleException(HttpServletResponse response, Exception ex) {
        Class eClass = ex.getClass();
        Result<Object> result = new Result<>();
        result.setResult(Result.RESULT_FLG.FAIL.getValue());
        if (!eClass.equals(BaseCustomException.class)) {
            log.error(ExceptionUtils.getStackTrace(ex));
        }
        //以下异常中，除注释过的，其他异常可不关注
        if (eClass.equals(MissingServletRequestParameterException.class)) {
            addResCodeToMap(BASE_RESP_CODE_ENUM.MIS_REQ_PARAM, result);
        } else if (eClass.equals(TypeMismatchException.class)) {
            addResCodeToMap(BASE_RESP_CODE_ENUM.MIS_REQ_PARAM, result);
        } else if (eClass.equals(HttpMessageNotReadableException.class)) {
            addResCodeToMap(BASE_RESP_CODE_ENUM.MIS_REQ_PARAM, result);
        } else if (eClass.equals(HttpRequestMethodNotSupportedException.class)) {
            addResCodeToMap(BASE_RESP_CODE_ENUM.METHOD_NOT_SUPPORTED, result);
        } else if (eClass.equals(HttpMediaTypeNotAcceptableException.class)) {
            addResCodeToMap(BASE_RESP_CODE_ENUM.MEDIA_TYPE_NOT_ACCEPT, result);
        } else if (eClass.equals(HttpMediaTypeNotSupportedException.class)) {
            addResCodeToMap(BASE_RESP_CODE_ENUM.MEDIA_TYPE_NOT_SUPPORTED, result);
        } else if (eClass.equals(ConversionNotSupportedException.class)) {
            addResCodeToMap(BASE_RESP_CODE_ENUM.SERVER_ERROR, result);
        } else if (eClass.equals(HttpMessageNotWritableException.class)) {
            addResCodeToMap(BASE_RESP_CODE_ENUM.SERVER_ERROR, result);
        } else if (eClass.equals(BaseCustomException.class)) { //系统业务异常
            addExceptionToMap((BaseCustomException) ex, result);
        } else if (eClass.equals(CustomException.class)) { //系统业务异常
            CustomException ce = (CustomException) ex;
            addExceptionToMap(new CustomException(ce.getErrorCode(), ce.getMessage()), result);
        } else {
            addResCodeToMap(BASE_RESP_CODE_ENUM.SERVER_ERROR, result);
        }

        // 错误相应编码回写
        PrintWriter writer = null;
        try {
            response.setContentType("application/json; charset=UTF-8");
            writer = response.getWriter();
            writer.write(JSONObject.fromObject(result).toString());
            writer.flush();
        } catch (Exception e) {
            IOUtils.closeQuietly(writer);
            log.error("接口异常:{}", ExceptionUtils.getFullStackTrace(e));
        }
    }

    /**
     * 添加系统异常信息到map中
     *
     * @param responseCodeEnum 错误响应编码枚举类对象
     * @param result           响应错误编码集合
     */
    protected void addResCodeToMap(BASE_RESP_CODE_ENUM responseCodeEnum, Result<Object> result) {
        result.setErrorCode(responseCodeEnum.getCode());
        result.setErrorMsg(responseCodeEnum.getMsg());
    }

    /**
     * 添加业务异常信息到map中
     *
     * @param responseCodeEnum 错误响应编码枚举类对象
     * @param result           响应错误编码集合
     */
    protected void addResCodeToMap(RESP_CODE_ENUM responseCodeEnum, Result<Object> result) {
        result.setErrorCode(responseCodeEnum.getCode());
        result.setErrorMsg(responseCodeEnum.getMsg());
    }

    /**
     * 添加异常信息到map中
     *
     * @param baseCustomException 接口异常类
     * @param result              接口异常集合
     */
    protected void addExceptionToMap(BaseCustomException baseCustomException, Result<Object> result) {
        result.setErrorCode(baseCustomException.getErrorCode());
        result.setErrorMsg(baseCustomException.getErrorMsg());
    }

    /**
     * 添加异常信息到map中
     *
     * @param customException 接口异常类
     * @param result          接口异常集合
     */
    protected void addExceptionToMap(CustomException customException, Result<Object> result) {
        result.setErrorCode(customException.getErrorCode());
        result.setErrorMsg(customException.getErrorMsg());
    }

    /**
     * 添加数据到结果对象中
     *
     * @param data 封装接口集合参数
     * @return
     */
    public Result getResult(Object data) {
        Result result = new Result();
        result.setResult(Result.RESULT_FLG.SUCCESS.getValue());
        result.setData(data);
        return result;
    }

}
