package com.goafanti.common.error;

import com.goafanti.common.bo.Error;
import com.goafanti.common.bo.Result;
import com.goafanti.common.utils.LoggerUtils;
import com.goafanti.common.utils.StringUtils;
import com.goafanti.core.shiro.filter.ShiroFilterUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.support.ResourcePropertySource;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.MessageFormat;

public class SystemExceptionResolver extends SimpleMappingExceptionResolver{
	@Resource(name = "errorResource")
	private ResourcePropertySource	errorResource;
	@Value(value = "${app.name}")
	private String appName;
	@Autowired
	private ShiroFilterUtils		shiroFilterUtils;

	@Override
	protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
			Exception ex) {
		/*if(request.getHeader("User-Agent") != null && request.getHeader("User-Agent").indexOf(appName) > -1){
			setExceptionMappings(new Properties());
			return null;
		}
		*/
		// Expose ModelAndView for chosen error view.
		String viewName = determineViewName(ex, request);

		ex = handleErrorMessage(ex);

		if (viewName != null) {
			if (!shiroFilterUtils.isAjax(request)) {// JSP
				// Apply HTTP status code for error views, if specified.
				// Only apply it if we're processing a top-level request.
				Integer statusCode = determineStatusCode(request, viewName);
				if (statusCode != null) {
					applyStatusCodeIfPossible(request, response, statusCode);
				}
				return getModelAndView(viewName, ex, request);
			} else {// JSON
				Result res = new Result();
				res.getError().add(new Error(viewName,ex.getMessage()));
				shiroFilterUtils.out(response, res);
				return null;
			}
		} else {
			return null;
		}
	}

	private Exception handleErrorMessage(Exception ex) {
		Error error = null;
		if (ex instanceof BusinessException) {
			BusinessException bex = (BusinessException) ex;
			String message = (String)errorResource.getProperty(bex.getCode());
			if(StringUtils.isEmpty(message)){
				error = new Error(bex.getCode(),bex.getMessage());
			}else{
				error = new Error(bex.getCode(), MessageFormat.format(message, bex.getField()));
			}
		} else if (ex instanceof IllegalArgumentException) {
			Object message = errorResource.getProperty(ex.getMessage());
			if (message == null) {
				message = errorResource.getProperty(ex.getClass().getName());
			}
			error = new Error((String) message);
		}else if (ex instanceof ClassCastException) {
			Object message = errorResource.getProperty(ex.getMessage());
			if (message == null) {
				message = errorResource.getProperty(ex.getClass().getName());
			}
			error = new Error((String) message);
		}else if (ex instanceof MaxUploadSizeExceededException) {
			Object message = errorResource.getProperty(ex.getMessage());
			if (message == null) {
				message = errorResource.getProperty(ex.getClass().getName());
			}
			error = new Error((String) message);
		}else {
			error = new Error((String) errorResource.getProperty(ex.getClass().getName()));
			LoggerUtils.fmtError(getClass(), ex, "数据异常。",ex.getClass().getName());
		}
		if (StringUtils.isEmpty(error.getMessage())) {
			error.setMessage("数据异常，请稍后再试，如再失败请联系管理员。");
		}
		return new BusinessException(error, ex.getCause());
	}

	/**
	 * @param errorResource
	 *            the errorResource to set
	 */
	public void setErrorResource(ResourcePropertySource errorResource) {
		this.errorResource = errorResource;
	}

}
