package nc.net.servlet;

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

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

import nc.bcmanage.bs.IBusiCenterManageService;
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.uap.IUAPQueryBS;
import nc.itf.ws.esb.IEsbDAO;
import nc.jdbc.framework.processor.ColumnProcessor;
import nc.pub.sap.constant.SapConstants;
import nc.pubitf.para.SysInitQuery;
import nc.vo.esb.EsbInfoVO;
import nc.vo.esb.EsbVO;
import nc.vo.esb.QueryInfoVO;
import nc.vo.esb.ResultEsbVO;
import nc.vo.esb.ResultVO;
import nc.vo.pub.BusinessException;
import nc.vo.ws.esb.CertificateVO;
import nc.vo.ws.esb.EsbinfoVO;
import uap.json.JSONObject;

/**
 * 对接ESB 包装Servlet类
 * @author 廖声豪 2018-04-09
 *
 */
public abstract class EsbJsonServlet implements IHttpServletAdaptor {
	
	/**
	 * 交互时间精确到毫秒
	 */
	public static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
	
	private static IEsbDAO service;
	
	private JSONObject jsonvalue;
	
	private String beginDateStr;
	
	@Override
	public void doAction(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		beginDateStr=dateFormat.format(Calendar.getInstance().getTime());//请求处理开始时间
		initInvocationInfo();
		if(true){//验证通过处理checkEsbkey(request)
			try{
				jsonvalue=findPostJsonValue(request);//获取Post请求的值
				if(jsonvalue==null || "".equals(jsonvalue)){//无Post提交值
					ResultVO result=new ResultVO();
					result.setCode(IReturnStatus.FAILING);//失败
					result.setMessage("Post所提交请求Json格式错误或者无值!");
					ResultEsbVO<ResultVO> esb=new ResultEsbVO<ResultVO>();
					createResultEsbVO(esb);
					esb.getEsbInfo().setReturnStatus(IReturnStatus.ESB_FAILING);
					esb.setResultInfo(result);
					sendResponse(response,esb);
				}else{
					/** begin 构建系统参数（BGY） 
				    try{

					    IBusiCenterManageService busiCenterManageService=NCLocator.getInstance().lookup(IBusiCenterManageService.class);
						InvocationInfoProxy.getInstance().setUserDataSource(busiCenterManageService.getAvailableBusiCenterDsNames()[0]);
						InvocationInfoProxy.getInstance().setGroupId(SysInitQuery.getParaString("GLOBLE00000000000000", "GROUP"));
						InvocationInfoProxy.getInstance().setUserId(SysInitQuery.getParaString("GLOBLE00000000000000", "ITFUSER"));
						ISecurityTokenCallback tc = NCLocator.getInstance().lookup(
								ISecurityTokenCallback.class);
						byte[] token = tc.token("__system".getBytes(), "NC".getBytes());
						NetStreamContext.setToken(token);
					    
					    
				    }catch(Exception e){
					    throw e;
				    }**/
				    /** end 构建系统参数（BGY） **/
					execFunction(request,response);
				}
			}catch(Exception e){
				ResultVO result=new ResultVO();
				result.setCode(IReturnStatus.ERROR);//异常
				result.setError(getExceptionDetail(e));
				ResultEsbVO<ResultVO> esb=new ResultEsbVO<ResultVO>();//创建响应对象
				createResultEsbVO(esb);//初始化响应对象
				esb.getEsbInfo().setReturnStatus(IReturnStatus.ESB_ERROR);
				esb.setResultInfo(result);//设置响应内容
				sendResponse(response,esb);
			}
		}else{//验证失败处理
			ResultVO result=new ResultVO();
			result.setCode(IReturnStatus.FAILING);//失败
			String esbkey=request.getHeader("esbkey");
			if(esbkey==null){
				result.setMessage("esbkey为空，授权验证失败!");
			}else{
				result.setMessage("esbkey授权验证失败!请检擦["+esbkey+"]是否为已认证key值!");
			}
			ResultEsbVO<ResultVO> esb=new ResultEsbVO<ResultVO>();//创建响应对象
			createResultEsbVO(esb);//初始化响应对象
			esb.getEsbInfo().setReturnStatus(IReturnStatus.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());
    			EsbinfoVO[] esbinfos=(EsbinfoVO[]) getService().findESB("interfacename='"+pathinfo+"'");
    			if(esbinfos!=null && esbinfos.length>0){
    				String esbkey=request.getHeader("esbkey");
    				for(EsbinfoVO esb:esbinfos){
    					if(esb.getIsstart()!=null && "1".equals(esb.getIsstart())){//检擦是否启用
	    					CertificateVO typevo=getService().findByPkCode(esb.getCertificate());
	    					if(typevo==null||!typevo.getEsbkey().equals(esbkey)){
	    						isok=false;
	    						break;
	    					}
    					}else{
    						isok=false;
    						break;
    					}
    				}
    			}else{
    				isok=false;
    			}
    		}
    	}catch(Exception e){
    		isok=false;
    	}
    	return isok;
	}
	
	/**
	 * 加载Post提交上来的Json参数
	 * @param request
	 * @return
	 * @throws Exception 
	 */
	private JSONObject findPostJsonValue(final HttpServletRequest request) throws Exception{
		BufferedReader br=null;
		try {
			br= new BufferedReader(new InputStreamReader(
					(ServletInputStream) request.getInputStream(), "utf-8"));
			StringBuffer sb = new StringBuffer();
			String temp=null;
			while ((temp = br.readLine())!= null) {
				sb.append(temp);
			}
			return new JSONObject(sb.toString());
		} catch (Exception e) {
			throw e;
		}finally{
			try {
				if(br!=null)
					br.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 发送响应信息
	 * @param response
	 * @param esb
	 */
	public void sendResponse(final HttpServletResponse response,ResultEsbVO 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();
			}
		}
	}
	
	/**
	 * Post请求所提交的Json
	 * @return
	 */
	public JSONObject getPostJsonValue(){
		return jsonvalue;
	}
	
	/**
	 * ESB 逻辑处理接口
	 * @return
	 */
	private static IEsbDAO getService(){
    	if(service==null)
    		service=NCLocator.getInstance().lookup(IEsbDAO.class);
    	return service;
	}
	
	/**
	 * 创建ESB交互对象
	 * @param newi
	 * @param esb 交互VO
	 * @return newi=0(请求对象)
	 */
	public void createEsbVO(final EsbVO esb){
		EsbInfoVO esbInfo=new EsbInfoVO();
		QueryInfoVO queryInfo=new QueryInfoVO();
		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 ResultEsbVO esb){
		EsbInfoVO esbInfo=new EsbInfoVO();
		QueryInfoVO queryInfo=new QueryInfoVO();
		Date date=Calendar.getInstance().getTime();//获取当前时间
		//设置响应时间
		String instid=getRequestInstId();
		if(instid!=null && !"".equals(instid)){
			esbInfo.setInstId(instid);
		}else{
			esbInfo.setInstId(getStringUUID());//使用UUID作为流水号
		}
		esbInfo.setRequestTime(getBeginDateStr());//设置请求开始时间
		esbInfo.setResponseTime(dateFormat.format(date));//设置响应时间
		esbInfo.setReturnStatus(IReturnStatus.ESB_SUCCEED);//默认响应成功
		esbInfo.setReturnCode(IReturnStatus.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;
	}
	
	/**
	 * 获取请求 instId 值
	 * @return
	 */
	public String getRequestInstId(){
		if(jsonvalue!=null){
			return jsonvalue.getJSONObject("esbInfo").getString("instId");
		}
		return null;
	}
	
	/**
	 * 业务逻辑执行函数
	 * @param request
	 * @param response
	 */
	public abstract void execFunction(HttpServletRequest request, HttpServletResponse response);
	
	private void initInvocationInfo() {
		/*
		 * ISecurityTokenCallback tc = NCLocator.getInstance().lookup(
		 * ISecurityTokenCallback.class); byte[] token = tc.token("__system".getBytes(),
		 * "NC".getBytes()); NetStreamContext.setToken(token); //NCC管理员 String
		 * sql="select cuserid from sm_user where user_code ='NCCadmin'"; String cuserid
		 * =""; try { cuserid = (String) getUAPQueryBS().executeQuery(sql, new
		 * ColumnProcessor()); } catch (BusinessException e) { e.printStackTrace(); } //
		 * InvocationInfoProxy.getInstance().setUserDataSource(SapConstants.NUMSOURSE);
		 * try {
		 * InvocationInfoProxy.getInstance().setGroupId(SysInitQuery.getParaString(
		 * "GLOBLE00000000000000", "GROUP")); } catch (BusinessException e) { // TODO
		 * Auto-generated catch block e.printStackTrace(); }
		 * InvocationInfoProxy.getInstance().setUserId(cuserid);
		 */
		
		try {
			IBusiCenterManageService busiCenterManageService=NCLocator.getInstance().lookup(IBusiCenterManageService.class);
			InvocationInfoProxy.getInstance().setUserDataSource(busiCenterManageService.getAvailableBusiCenterDsNames()[0]);
			InvocationInfoProxy.getInstance().setGroupId(SysInitQuery.getParaString("GLOBLE00000000000000", "GROUP"));
			InvocationInfoProxy.getInstance().setUserId(SysInitQuery.getParaString("GLOBLE00000000000000", "ITFUSER"));
		} catch (BusinessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		ISecurityTokenCallback tc = NCLocator.getInstance().lookup(
				ISecurityTokenCallback.class);
		byte[] token = tc.token("__system".getBytes(), "NC".getBytes());
		NetStreamContext.setToken(token);

	}
	
	private IUAPQueryBS uapQueryBS;
    public IUAPQueryBS getUAPQueryBS() {
        if (uapQueryBS == null) {
        uapQueryBS = NCLocator.getInstance().lookup(IUAPQueryBS.class);
        }
        return uapQueryBS;
        }
}
