package ncc.net.servlet;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import nc.bs.dao.BaseDAO;
import nc.bs.framework.adaptor.IHttpServletAdaptor;
import nc.bs.framework.common.InvocationInfoProxy;
import nc.bs.framework.common.NCLocator;
import nc.bs.framework.comn.NetStreamContext;
import nc.bs.framework.server.ISecurityTokenCallback;
import nc.itf.ws.esb.IEsbDAO;
import nc.jdbc.framework.processor.ColumnProcessor;
import nc.jdbc.framework.processor.MapProcessor;
import ncc.net.servlet.status.WyReturnStatus;
import ncc.pub.wy.constant.WyConstants;
import ncc.vo.esb.WyEsbInfoVO;
import ncc.vo.esb.WyEsbVO;
import ncc.vo.esb.WyQueryInfoVO;
import ncc.vo.esb.WyResultEsbVO;
import ncc.vo.esb.result.WyResultVO;

/**
 * 对接ESB 包装Servlet类
 * @author 周蓝萍
 * @date 2020-12-03
 *
 */
public abstract class NccEsbJsonServletUtil implements IHttpServletAdaptor {
	
	/**
	 * 交互时间精确到毫秒
	 */
	public static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
	
	private static IEsbDAO service;
	
	
	private String beginDateStr;
	
	@Override
	public void doAction(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		beginDateStr=dateFormat.format(Calendar.getInstance().getTime());//请求处理开始时间
		initInvocationInfo();
//		if(checkEsbkey(request)){//验证通过处理
		if(true){	
			execFunction(request,response);
			
		}else{//验证失败处理
			WyResultVO result=new WyResultVO();
			result.setCode(WyReturnStatus.FAILING);//失败
			String esbkey=request.getHeader("esbkey");
			if(esbkey==null){
				result.setMessage("esbkey为空，授权验证失败!");
			}else{
				result.setMessage("esbkey授权验证失败!请检查["+esbkey+"]是否为已认证key值!");
			}
			WyResultEsbVO<WyResultVO> esb=new WyResultEsbVO<WyResultVO>();//创建响应对象
			createResultEsbVO(esb);//初始化响应对象
			esb.getEsbInfo().setReturnStatus(WyReturnStatus.ESB_FAILING);
			esb.setResultInfo(result);
			sendResponse(response,esb);
		}
	}
	
	/**
	 * 验证esbkey
	 * @param request 
	 * @return true(验证通过)/false(验证失败)
	 */
	private boolean checkEsbkey(final HttpServletRequest request){
		boolean isok=true;
    	try{
    		String pathinfo=request.getPathInfo();
    		if(pathinfo!=null){
    			pathinfo=pathinfo.substring(1, pathinfo.length());
    			String sql = "select distinct isstart,certificate from bgy_esbinfo where interfacename='"+pathinfo+"'";
    			Map map = (Map) new BaseDAO().executeQuery(sql, new MapProcessor());
    			String isstart = "";
    			String certificate = "";
    			if(null != map && map.size()>0) {
    				String esbkey=request.getHeader("esbkey");
    				isstart = (String) map.get("isstart");
    				certificate = (String) map.get("certificate");
    				if(null != isstart && "1".equals(isstart) && null !=certificate) {//检查是否启用
    					String sjesbkey = "select esbkey from bgy_certificate where pk_code='"+certificate+"'";
    					String esb = (String) new BaseDAO().executeQuery(sjesbkey, new ColumnProcessor());
    					if(null == esb ||!esb.equals(esbkey)) {
    						isok=false;
    					}
    				}else{
						isok=false;
					}
    			}else{
    				isok=false;
    			}
    		}
    	}catch(Exception e){
    		isok=false;
    	}
    	return isok;
	}
	
	
	/**
	 * 发送响应信息
	 * @param response
	 * @param esb
	 */
	public void sendResponse(final HttpServletResponse response,WyResultEsbVO esb){
		String jsondata=com.alibaba.fastjson.JSONObject.toJSONString(esb);
		PrintWriter out=null;
		try {
			response.setHeader("Content-type", "application/json;charset=UTF-8");
			out = new PrintWriter(new OutputStreamWriter(response.getOutputStream(),"UTF-8"));
	        out.write(jsondata);
	        out.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if(out!=null){
				out.close();
			}
		}
	}
	
	
	/**
	 * 创建ESB交互对象
	 * @param newi
	 * @param esb 交互VO
	 * @return newi=0(请求对象)
	 */
	public void createEsbVO(final WyEsbVO esb){
		WyEsbInfoVO esbInfo=new WyEsbInfoVO();
		WyQueryInfoVO queryInfo=new WyQueryInfoVO();
		Date date=Calendar.getInstance().getTime();//获取当前时间
		//设置请求时间
		esbInfo.setRequestTime(dateFormat.format(date));
		esbInfo.setInstId(getStringUUID());//使用UUID作为流水号
		esb.setEsbInfo(esbInfo);
		esb.setQueryInfo(queryInfo);
	}
	/**
	 * 生成ESB响应对象
	 * @param esb
	 */
	public void createResultEsbVO(final WyResultEsbVO esb){
		WyEsbInfoVO esbInfo=new WyEsbInfoVO();
		WyQueryInfoVO queryInfo=new WyQueryInfoVO();
		Date date=Calendar.getInstance().getTime();//获取当前时间
		//设置响应时间
		esbInfo.setInstId(getStringUUID());//使用UUID作为流水号
		esbInfo.setRequestTime(getBeginDateStr());//设置请求开始时间
		esbInfo.setResponseTime(dateFormat.format(date));//设置响应时间
		esbInfo.setReturnStatus(WyReturnStatus.ESB_SUCCEED);//默认响应成功
		esbInfo.setReturnCode(WyReturnStatus.ESB_SUCCEED_CODE);//默认成功code
		esbInfo.setReturnMsg("成功");//默认响应成功提示
		esb.setEsbInfo(esbInfo);
		esb.setQueryInfo(queryInfo);
	}
	
	/**
	 * 获得UUID值
	 */
	public static String getStringUUID(){
		return UUID.randomUUID().toString();
	}
	
	/**
	 * @param e	异常
	 * return 异常详细信息
	 */
	public String getExceptionDetail(Exception e) {  
		if(e==null)
			return null;
        StringBuffer stringBuffer = new StringBuffer(e.toString() + "\n");  
        if(e.getStackTrace()==null || e.getStackTrace().length==0)
        	return stringBuffer.toString();  
        StackTraceElement[] messages = e.getStackTrace();  
        int length = messages.length;  
        for (int i = 0; i < length; i++) {
            stringBuffer.append("\t"+messages[i].toString()+"\n");  
        }  
        return stringBuffer.toString();  
    }
	
	/**
	 * 请求处理开始时间
	 * @return
	 */
	public String getBeginDateStr(){
		return beginDateStr;
	}
	
	
	/**
	 * 业务逻辑执行函数
	 * @param request
	 * @param response
	 */
	public abstract void execFunction(HttpServletRequest request, HttpServletResponse response);
	
	protected void initInvocationInfo() {
		
		InvocationInfoProxy.getInstance().setUserDataSource("NCCDATA");
		//InvocationInfoProxy.getInstance().setUserDataSource(WyConstants.NUMSOURSE);
		InvocationInfoProxy.getInstance().setGroupId(WyConstants.GROUPID);
		InvocationInfoProxy.getInstance().setUserId(
				WyConstants.NCCADMIN_CUSERID);
		ISecurityTokenCallback tc = NCLocator.getInstance().lookup(
				ISecurityTokenCallback.class);
		byte[] token = tc.token("__system".getBytes(), "NC".getBytes());
		NetStreamContext.setToken(token);
	}
}
