/**
 * Project Name:activity-access-web File Name:BaseController.java Package Name:com.duiba.activity.accessweb.controller
 * Date:2016年10月9日上午8:59:58 Copyright (c) 2016, duiba.com.cn All Rights Reserved.
 */

package com.duiba.tuia.youtui.web.controller;

import cn.com.duiba.boot.exception.BizException;
import cn.com.duiba.tuia.activity.center.api.exception.ActivityCenterRuntimeException;
import com.duiba.tuia.youtui.web.constant.ErrorCode;
import com.duiba.tuia.youtui.web.exception.ActivityException;
import com.duiba.tuia.youtui.web.exception.ActivityRuntimeException;
import com.duiba.tuia.youtui.web.exception.BusinessException;
import com.duiba.tuia.youtui.web.model.Result;
import com.duiba.tuia.youtui.web.model.UserAccount;
import com.duiba.tuia.youtui.web.tool.RequestLocal;
import com.duiba.tuia.youtui.web.tool.RequestTool;
import com.duiba.tuia.youtui.web.tool.ResultUtil;
import com.netflix.hystrix.exception.HystrixRuntimeException;
import org.apache.catalina.connector.ClientAbortException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;

import javax.servlet.http.HttpServletRequest;

/**
 * ClassName:BaseController <br/>
 * Date: 2016年10月9日 上午8:59:58 <br/>
 * .
 *
 * @author zhanglihui
 * @version
 * @since JDK 1.6
 * @see
 */
public class BaseController {

    /** The logger. */
    protected final Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * 参数校验.
     *
     * @param result the result
     * @throws ActivityException the activity exception
     */
    public void paramAuth(BindingResult result) throws ActivityException {
        if (result.hasErrors()) {
            logger.info("[param] error, because of " + result.getFieldError());
            throw new ActivityException(ErrorCode.E0000001.geteCode(), result.getFieldError().getDefaultMessage());
        }
    }

    /**
     * Fail result.
     *
     * @param <T> the generic type
     * @param e the e
     * @return the result< t>
     */
    @ExceptionHandler
    public <T> Result<T> failResult(Exception e) {
        if (e instanceof BusinessException) {
            return ResultUtil.fail(((BusinessException) e).getCode(), e.getMessage());
        } else if (e instanceof ActivityException) {
            ActivityException e1 = (ActivityException) e;
            logger.info("发生内部错误, because of=[{}],用户IP=[{}]", e1.getMessage(), RequestLocal.get().getIp());
            return ResultUtil.fail(e1.getCode(), e1.getMessage());
        } else if (e instanceof ClientAbortException) {
            logger.info("发生外部错误, because of=[{用户主动关闭链接，ClientAbortException}]");
            return null;
        } else if (e instanceof IllegalStateException) {
            logger.info("发生外部错误, because of=[{getOutputStream() has already been called for this response}]");
            return null;
        } else if (e instanceof MissingServletRequestParameterException) {
            logger.info("发生外部错误, because of=[{用户传参数错误，MissingServletRequestParameterException}]");
            return null;
        } else if (e instanceof ActivityRuntimeException) {
            logger.warn("发生系统错误", e);
            return ResultUtil.fail(((ActivityRuntimeException) e).getCode(), e.getMessage());
        } else if (e instanceof HystrixRuntimeException && e.getCause() instanceof BizException) {
            BizException bizException = (BizException) e.getCause();
            return ResultUtil.fail(bizException.getCode(), bizException.getMessage());
        } else if (e instanceof HystrixRuntimeException && e.getCause() instanceof ActivityCenterRuntimeException) {
            ActivityCenterRuntimeException exception = (ActivityCenterRuntimeException) e.getCause();
            return ResultUtil.fail(exception.getCode(), exception.getMessage());
        } else if (e instanceof BindException) {
            logger.info("发生系统错误,用户IP=[{}]", RequestLocal.get().getIp(), e);
            return ResultUtil.fail(ErrorCode.E9999999);
        } else {
            logger.warn("发生系统错误,用户IP=[{}]", RequestLocal.get().getIp(), e);
            return ResultUtil.fail(ErrorCode.E9999999);
        }
    }

    /**
     * Success result.
     *
     * @param <T> the generic type
     * @param t the t
     * @return the result< t>
     */
    public <T> Result<T> successResult(T t) {
        return ResultUtil.success(t);
    }

    /**
     * Success result.
     *
     * @param <T> the generic type
     * @return the result< t>
     */
    public <T> Result<T> successResult() {
        return ResultUtil.success();
    }

    protected void checkUser(HttpServletRequest request) throws BusinessException {
        // 1.获取用户信息
        RequestLocal.get().setRequest(request);
        UserAccount consumer = RequestLocal.get().getUserAccount();
        if (null == consumer) {
            logger.info("用户信息异常。ConsumerId is null");
            throw new BusinessException(ErrorCode.E0200001);
        }
    }

    /***
     * @Description: checkLogin 校验用户登录状态
     *
     * @Param: [request]
     * @Return: void
     * @throws:
     * @author: youhaijun
     * @Date: 2017/12/13
     */
    protected void checkLogin() throws BusinessException {
        UserAccount consumer = RequestLocal.get().getUserAccount();
        Boolean loginStatus = consumer.getLoginStatus();
        if (null == loginStatus || !loginStatus) {
            logger.info("用户处于未登录状态，无权调用接口");
            throw new BusinessException(ErrorCode.E0200003);
        }
    }

    protected String getIp(HttpServletRequest request) {
        // 测试ip用，便于测试
        String ip = request.getParameter("testIp");
        if (StringUtils.isNotBlank(ip)) {
            return ip;
        }
        return RequestTool.getIpAddr(request);
    }
}
