/*
 * Copyright (C), 2002-2015, 江苏三六五网络股份有限公司
 * FileName: InterfaceController.java
 * Author:   duhui
 * Date:     2015年1月22日 上午11:39:07
 * Description:
 * History:
 * <author>      <time>      <version>    <desc>
 * 修改人姓名                          修改时间                        版本号                                 描述
 */
package com.house365.web.controller;

import com.google.common.base.Strings;
import com.house365.beans.po.IfRegPo;
import com.house365.rest.context.IService;
import com.house365.rest.context.Parameter;
import com.house365.rest.context.ServiceConstant;
import com.house365.rest.context.ServiceContext;
import com.house365.rest.exception.IllegalServiceParameterException;
import com.house365.rest.exception.ServiceConfigException;
import com.house365.rest.parameter.House365RestResponse;
import com.house365.web.util.Constant;
import com.house365.web.util.House365StringUtils;
import com.house365.web.util.StringUtils;
import com.house365.ws.interfaces.server.IIfRegInterface;
import com.house365.ws.system.ReturnAppResult;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 对外统一接口
 *
 * @author duhui
 * @version [v1.0.0, 2015年1月22日]
 * @see [相关类/方法]（可选）
 * @since [产品/模块版本] （可选）
 */
@Controller
@RequestMapping(value = {"/rest", "/secure/rest"})
public class InterfaceController {

    /**
     * 日志记录器
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(InterfaceController.class);

    /**
     * 注入接口服务
     */
    @Autowired
    private IIfRegInterface ifRegInterface;

    /**
     * 统一入口分发
     *
     * @param request 公共参数
     * @return 处理结果json字符串
     * @author duhui
     * @version [v1.0.0, 2015年1月22日]
     */
    @SuppressWarnings("unchecked")
    @RequestMapping(value = "interface", method = {RequestMethod.GET, RequestMethod.POST}, produces = {"application/json;charset=UTF-8"})
    @ResponseBody
    public String interfaceOut(
            HttpServletRequest request, @RequestBody(required = false) String entity
    ) throws Exception {
        House365RestResponse<Object> response = new House365RestResponse<>();
        Object result = null;
        Map<String, Object> map = new HashMap<String, Object>(request.getParameterMap());
        // 统一入口校验 业务层只需校验自己所需参数是否存在
        try {
            checkInterfaceParameter(map);
        } catch (IllegalServiceParameterException e) {
            response.setResult(ReturnAppResult.APP_FAIL.getResultCode());
            response.setMsg(e.getMessage());
            return JSONObject.fromObject(response).toString();
        }

        String serviceCode = String.valueOf(map.get(
                ServiceConstant.SERVICE_CODE).getClass().isArray() ? ((String[]) map.get(
                ServiceConstant.SERVICE_CODE))[0] : map.get(ServiceConstant.SERVICE_CODE));
        String serviceName = String.valueOf(map.get(
                ServiceConstant.SERVICE_NAME).getClass().isArray() ? ((String[]) map.get(
                ServiceConstant.SERVICE_NAME))[0] : map.get(ServiceConstant.SERVICE_NAME));
        if (Strings.isNullOrEmpty(serviceCode) || Strings.isNullOrEmpty(serviceName)) {
            LOGGER.error("配置执行服务异常：找不到对应服务编码 服务名称!");
            throw new ServiceConfigException("配置执行服务异常：找不到对应服务编码 服务名称!");
        }

        // 接口服务校验 如果有异常可发送消息通知负责人
        IService service;
        try {
            service = checkAndGetServiceReg(map);
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
            response.setResult(ReturnAppResult.APP_FAIL.getResultCode());
            response.setMsg(e.getMessage());
            return JSONObject.fromObject(response).toString();
        }
        // 封装请求参数
        Parameter parameter = new Parameter();
        parameter = new Parameter();
        parameter.setArgs(map);
        // 执行结果
        //        result = ServiceContext.getInstance().startService(service, parameter);

        // 之前接口只可以执行execute一个方法,保持接口纯洁同时增加了编码复杂度
        // 修改后：可自定义接口调用方法，但仍需注意保持接口功能单一 By xn 20151229
        if (Constant.HGS_SERVICE_CODE.equals(serviceCode)) {
            result = ServiceContext.getInstance().startService(service, parameter);
        } else if (Constant.WECHAT_HGS_SERVICE_CODE.equals(serviceCode)) {
            if (StringUtils.isNotBlank(entity)) {
                parameter.addArg("entity", entity);
            }
            result = ServiceContext.getInstance().startServiceWithMethodNew(service, parameter, serviceName);
        }

        return result.toString();
    }

    /**
     * 统一分发中心接口参数校验
     * 与小飞讨论后更改请求参数传递方式
     *
     * @return
     * @throws IllegalServiceParameterException 统一分发中心接口参数异常
     * @author duhui
     * @version [v1.0.0, 2015年1月22日]
     * @since [产品/模块版本](可选)
     */
    protected void checkInterfaceParameter(Map<String, Object> map) throws IllegalServiceParameterException {
        // 遍历校验
        for (String key : map.keySet()) {
            try {
                String value = ((String[]) map.get(key))[0];
                if (House365StringUtils.isEmpty(value)) {
                    LOGGER.debug("业务入口参数异常：" + key + "参数为空!");
                    throw new IllegalServiceParameterException("业务入口参数异常：" + key + "参数为空!");
                }
            } catch (Exception e) {
                throw new IllegalServiceParameterException("业务入口参数异常：" + key + "参数为空!");
            }
        }
    }

    /**
     * 校验并取得公共容器配置的执行服务
     *
     * @param map 入参
     * @return
     * @throws ServiceConfigException 服务参数配置异常
     * @author duhui
     * @version [v1.0.0, 2015年1月25日]
     * @since [产品/模块版本](可选)
     */
    protected IService checkAndGetServiceReg(Map<String, Object> map) throws ServiceConfigException {
        /**
         * 取得公共容器执行服务
         */
        IService iService = null;
        String serviceName = "";
        String serviceCode = "";
        try {

            serviceCode = ((String[]) map.get(ServiceConstant.SERVICE_CODE))[0];
            serviceName = ((String[]) map.get(ServiceConstant.SERVICE_NAME))[0];
            // 根据服务编码 服务名称 取得执行的服务
            List<IfRegPo> ifRegPoList = ifRegInterface.getIfRegServiceReg(serviceCode, serviceName);
            // 找不到执行的服务
            if (null == ifRegPoList || ifRegPoList.isEmpty()) {
                LOGGER.error("配置执行服务异常：根据服务编码 服务名称找不到对应执行服务!");
                throw new ServiceConfigException("配置执行服务异常：根据服务编码 服务名称找不到对应执行服务!");
            }
            // 找到多个执行的服务 默认取一个执行 须记录改正下
            if (ifRegPoList.size() > 1) {
                LOGGER.warn("配置执行服务警告：根据服务编码 服务名称找到多个执行服务!");
            }
            // 取得执行的服务
            IfRegPo ifRegPo = ifRegPoList.get(0);
            String serviceReg = ifRegPo.getServiceReg();
            iService = ServiceContext.getInstance().createServiceInstance(serviceReg);
        } catch (Exception e) {
            LOGGER.error("配置执行服务异常：配置的执行服务没有发布![{}]", serviceCode + "_" + serviceName);
            throw new ServiceConfigException("配置执行服务异常：配置的执行服务没有发布!");
        }
        return iService;
    }
}
