package libedge.exception;

import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMap;
import libedge.domain.exceptions.GenericException;
import libedge.domain.exceptions.TooManyRequestsException;
import lombok.extern.slf4j.Slf4j;
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.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.Map;

/**
 * @author Created by Mike He on 2017/3/7.
 */
@Slf4j
@ControllerAdvice
public class GlobalControllerExceptionHandler {

	public static Map<String, String> errorResponse(Throwable throwable) {
		Throwable cause = Throwables.getRootCause(throwable);
		String message = String.valueOf(cause.getMessage());
		if (GenericException.class.isInstance(throwable)) {
			return ImmutableMap.of("message", message, "code", ((GenericException) throwable).getCode());
		}
		if(throwable instanceof UndeclaredThrowableException){
			Throwable exception = ((UndeclaredThrowableException) throwable).getUndeclaredThrowable();
			if(exception instanceof GenericException){
				return ImmutableMap.of("message", message, "code", ((GenericException) exception).getCode());
			}
		}
		log.error("Expected error. ", throwable);
		return ImmutableMap.of("message", message, "code", "1998001");
	}

	@ResponseBody
	@ResponseStatus(HttpStatus.OK)
	@ExceptionHandler({Exception.class})
	public Map<String, String> handleException(Throwable e) {
		log.warn("HANDLED EXCEPTION: {}", e.getMessage(), e);
		return errorResponse(e);
	}

	@ResponseBody
	@ResponseStatus(HttpStatus.OK)
	@ExceptionHandler({IllegalArgumentException.class})
	public Map<String, String> handleException(IllegalArgumentException e) {
		e.printStackTrace();
		return ImmutableMap.of("code", "1911001", "message", e.getMessage());
	}

	@ResponseBody
	@ResponseStatus(HttpStatus.TOO_MANY_REQUESTS)
	@ExceptionHandler({TooManyRequestsException.class})
	public Map<String, String> handleException(TooManyRequestsException e) {
		return ImmutableMap.of("code", "1911002", "message", e.getMessage());
	}

	@ResponseBody
	@ResponseStatus(HttpStatus.OK)
	@ExceptionHandler({ConstraintViolationException.class})
	public Map<String, String> handleException(ConstraintViolationException e) {
		StringBuilder message = new StringBuilder();
		for (ConstraintViolation<?> s : e.getConstraintViolations()) {
			message.append(s.getMessage());
		}
		log.warn("参数校验失败: {}", message.toString());
		return ImmutableMap.of("code", "1911001", "message", message.toString());
	}

}

@@ -254,16 +254,163 @@
 .Slf4j;%0A
+import org.apache.commons.lang3.StringUtils;%0Aimport org.apache.commons.lang3.exception.ExceptionUtils;%0Aimport org.springframework.http.HttpEntity;%0A
 import o
@@ -791,32 +791,60 @@
 ationException;%0A
+import java.io.IOException;%0A
 import java.lang
@@ -3013,10 +3013,421 @@
 ));%0A%09%7D%0A%0A
+  @ResponseBody%0A  @ResponseStatus(HttpStatus.SERVICE_UNAVAILABLE)%0A  @ExceptionHandler(%7BIOException.class%7D)%0A  public Object handleException(IOException e) %7B%0A    String searchStr = %22Broken pipe%22;%0A    if (StringUtils.containsIgnoreCase(ExceptionUtils.getRootCauseMessage(e), searchStr)) %7B%0A      log.error(%22Broken pipe%22, e);%0A      return null;%0A    %7D else %7B%0A      return new HttpEntity%3C%3E(e.getMessage());%0A    %7D%0A  %7D%0A%0A
 %7D%0A

add handler for exception about "broken pipe".