package com.yd.api;

import java.io.IOException;
import java.util.Map;

import javax.servlet.RequestDispatcher;
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.boot.autoconfigure.web.ErrorAttributes;
import org.springframework.boot.autoconfigure.web.ErrorController;
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.bind.annotation.ResponseBody;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.yd.api.result.CommonResult;
import com.yd.api.result.ErrorResponseVO;
import com.yd.api.result.JsonResult;

/**
 * 
 * @author Simon Cheng
 *
 */
@Controller
public class AppErrorController implements ErrorController{

    private static final Logger logger = LoggerFactory.getLogger(AppErrorController.class);

    private static AppErrorController appErrorController;

     /**
     * Error Attributes in the Application
     */
    @Autowired
    private ErrorAttributes errorAttributes;

    private final static String ERROR_PATH = "/error";

    /**
     * Controller for the Error Controller
     * @param errorAttributes
     * @return 
     */ 

    public AppErrorController(ErrorAttributes errorAttributes) {
        this.errorAttributes = errorAttributes;
    }

    public AppErrorController() {
        if(appErrorController == null){
            appErrorController = new AppErrorController(errorAttributes);
        }
    }

    /**
     * Supports the HTML Error View
     * @param request
     * @return
     */   
    @RequestMapping(value = ERROR_PATH, produces = "text/html")
    public void errorHtml(HttpServletRequest request,HttpServletResponse response) {
		Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
		String redirectURL = "/ydapi/errorunknown.html";
		if (status != null) {
		     Integer statusCode = Integer.valueOf(status.toString());
		     if (statusCode == HttpStatus.NOT_FOUND.value()) {
		    	 redirectURL = "/ydapi/error404.html";
		}else if(statusCode == HttpStatus.INTERNAL_SERVER_ERROR.value()) {
			 redirectURL = "/ydapi/error500.html";
		}else {
			 redirectURL = "/ydapi/errorunknown.html";
		    }
		}

		try {
			response.sendRedirect(redirectURL);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }
    
    /**
     * Supports other formats like JSON, XML
     * @param request
     * @return
     */
    @RequestMapping(value = ERROR_PATH)
    @ResponseBody
    public Object error(HttpServletRequest request) {
        Map<String, Object> body = getErrorAttributes(request, getTraceParameter(request));
        HttpStatus status = getStatus(request);
        
    	JsonResult result =  new JsonResult();
    	ErrorResponseVO errorResponseVO = new ErrorResponseVO();
    	
    	errorResponseVO.setCommonResult(new CommonResult(false,"API not exist! Please go to our home page https://www.ydinsurance.cn/"));
    	
		result.setData(new ResponseEntity<Map<String, Object>>(body, status));
	    result.addResult(errorResponseVO);
		return result;
    }

    /**
     * Returns the path of the error page.
     *
     * @return the error path
     */
    @Override
    public String getErrorPath() {
        return ERROR_PATH;
    }


    private boolean getTraceParameter(HttpServletRequest request) {
        String parameter = request.getParameter("trace");
        if (parameter == null) {
            return false;
        }
        return !"false".equals(parameter.toLowerCase());
    }

    private Map<String, Object> getErrorAttributes(HttpServletRequest request,
                                                   boolean includeStackTrace) {     
        RequestAttributes requestAttributes = new ServletRequestAttributes(request);       
        Map<String, Object> map = this.errorAttributes.getErrorAttributes(requestAttributes,includeStackTrace);  
        String URL = request.getRequestURL().toString();
        map.put("URL", URL);        
        logger.debug("AppErrorController.method [error info]: status-" + map.get("status") +", request url-" + URL);            
        return map;
    }

    private HttpStatus getStatus(HttpServletRequest request) {
        Integer statusCode = (Integer) request
                .getAttribute("javax.servlet.error.status_code");
        if (statusCode != null) {
            try {
                return HttpStatus.valueOf(statusCode);
            }
            catch (Exception ex) {
            }
        }
        return HttpStatus.INTERNAL_SERVER_ERROR;
    }   

}
