package com.nms.server.thread.detectDataHandler;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.LinkedBlockingDeque;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import com.fang.U;
import com.fang.lang.Db;
import com.fang.lang.StopWatch;
import com.nms.server.bean.DetectInfo;
import com.nms.server.bean.EmailInfo;
import com.nms.server.common.Common;
import com.nms.server.common.Constants;
import com.nms.server.common.EmailTypeConstants;
import com.nms.server.util.DateUtil;
import com.nms.server.util.StringUtil;

/**
 * detection_info 入库线程
 * 
 * @author nanfang
 * 
 *1、从info队列中获取元素 2、判断状态 3、每取 n 个 执行一次批量入库 
 * 
 * 
 */
public class DetectInfoInsertThread implements Runnable {
	private static final Logger logger = Logger.getLogger(DetectInfoInsertThread.class);
	private final SimpleDateFormat format = Common.getFormat(); // Java Date
																// 类型数据格式化格式
	private static Db db = Common.getDb();
	private StopWatch sw ;
	private int count = 0;// 计数
	// 监测设置对应的联系人email地址
	Map<String, List<String>> setInfoEmail = null;
	// 未指定的监测设置通过seqid找到对应的联系人
	Map<String, List<String>> seqIdEmail = null;

	private PreparedStatement infoStmt;
	private PreparedStatement warnStmt;
	private PreparedStatement emailStmt;
	private PreparedStatement statusChangeStmt;
	private PreparedStatement infoNewInsertStmt;
	private PreparedStatement infoNewUpdateStmt;
	private List<Object[]> insertDataTonew;
	private List<Object[]> updateDataTonew;
	private PreparedStatement warnUpdateStmt;
	private Connection conn;//使用的连接
	
	
	@Override
	@SuppressWarnings({ "unchecked", "static-access" })
	public void run() {
		Thread.currentThread().setName("DetectInfoInsertThread");
		logger.info("开始运行");
		sw = U.StopWatch.newStopWacth();
		sw.start();
		try {
			// info数据缓存队列
			LinkedBlockingDeque<Object[]> infoQueue = Common.DETECT_QUEUE.get(DetectInfo.INFO_KEY);
			if (infoQueue != null && infoQueue.size() > 0) {
				conn = db.getConnection();
				conn.setAutoCommit(false);
				Object[] info = null;
				List<Object[]> allInfo = U.newLinkedList();
				List<Object[]> params = U.newLinkedList();
				insertDataTonew=new ArrayList<Object[]>();
				updateDataTonew=new ArrayList<Object[]>();
				warnUpdateStmt=conn.prepareStatement(DetectInfo.getChangeWarningInfoSql());
				int total = infoQueue.drainTo(allInfo);//一次性把队列的数据全部取出
				for(int i = 0;i<total;i++){
					info = allInfo.get(i);
					if (info != null) {
						count++;
						infoSetDefaultVal(info);
						params.add(info);
						if (count % Constants.BATCH_RESOVE_COUNT == 0) {
							judgeAndSave(params);
							params.clear();
						}
					}
				}
				if(params.size() > 0){
					judgeAndSave(params);
					params.clear();
				}
				allInfo.clear();
			} else {
				logger.info("info queue is empty");
			}
		} catch (Exception e) {
			logger.error("error", e);
		}finally {
			db.closeQuiet(infoStmt,warnStmt,emailStmt,statusChangeStmt,conn,infoNewInsertStmt,infoNewUpdateStmt);
			infoStmt = null;
			warnStmt = null;
			emailStmt = null;
			statusChangeStmt = null;
			setInfoEmail = null;
			seqIdEmail = null;
			conn = null;
			infoNewInsertStmt=null;
			infoNewUpdateStmt=null;
		}
		sw.end();
		logger.info("监测数据info信息解析入库，耗时： " + U.StopWatch.toString(sw.total()) + " ,共 " + count + " 条");
		sw = null;
		count = 0;
	}

	/**
	 * 设置默认值
	 * @param detecInfo
	 */
	private void infoSetDefaultVal(Object[] detecInfo){
		/**
		 * 设置默认值
		 */
		if(detecInfo[DetectInfo.STATE] == null){
			detecInfo[DetectInfo.STATE] = -1;//state
		}
		if(detecInfo[DetectInfo.PLEVEL] == null){
			detecInfo[DetectInfo.PLEVEL] = 99;//pLevel
		}
		if(detecInfo[DetectInfo.DELYFLAG] == null){
			detecInfo[DetectInfo.DELYFLAG] = false;//delyFlag
		}
		if(detecInfo[DetectInfo.URGENTLEVEL] == null){
			detecInfo[DetectInfo.URGENTLEVEL] = 0;//urgentLevel
		}
		if(detecInfo[DetectInfo.SENDEMAILFLAG] == null){
			detecInfo[DetectInfo.SENDEMAILFLAG] = false;//sendEmailFlag
		}
		if(detecInfo[DetectInfo.STATECHANGEFLAG] == null){
			detecInfo[DetectInfo.STATECHANGEFLAG] = false;//stateChangeFlag
		}
		if(detecInfo[DetectInfo.STATUSCHANGTIME] == null){
			detecInfo[DetectInfo.STATUSCHANGTIME] = -1L;//statusChangeTime
		}
	}
	
	/**
	 * 判断状态并保存
	 * 
	 * @param params
	 */
	private void judgeAndSave(List<Object[]> params) {
		sw.tag("s" + count);
		try {
			long l = System.currentTimeMillis();
			sw.tag(l + "s");
			//seqId,setId,list<info>
			Map<String, Map<String, List<Object[]>>> orInfo = orderInfo(params);// 整理数据
			Set<String> seqIds = orInfo.keySet();
			// 获取 当前将要入库的数据 对应的 detection_info_new 表中的数据
			Map<String, Map<String, Object[]>> detectNewData = this.getDetectNewData(seqIds);
			// 判断状态变更
			for (String seqId : seqIds) {//遍历即将入库的数据
				Map<String, List<Object[]>> setMap = orInfo.get(seqId);
				Set<Entry<String, List<Object[]>>> setEn = setMap.entrySet();
				for (Entry<String, List<Object[]>> si : setEn) {
					String setId = si.getKey();// 监测设置id
					List<Object[]> allDeteInfo = si.getValue();// 将要入库的info数据
					Object[] oldDetecInfo = null;// new表中的最新记录
					// 获取 数据库 中 new 表的对应值
					Map<String, Object[]> seqMap = detectNewData.get(seqId);
					if (seqMap != null) {
						oldDetecInfo = seqMap.get(setId);
					}
					
					// 数据库中没有当前监测类别对应的seqid节点的监测信息，不需要判断状态变更
					if (oldDetecInfo != null) {
						judgeStatus(allDeteInfo, oldDetecInfo);
						judgeAndCollect(allDeteInfo, oldDetecInfo, updateDataTonew);
						
					}else{//如果new表中没有数据，应为detection_info status_change_time设置初始值-->data_check_time
						if(allDeteInfo!=null&&allDeteInfo.size()>0){
							for (Object[] newInfo : allDeteInfo) {
								if(newInfo[DetectInfo.STATUSCHANGTIME]==null||(Long)newInfo[DetectInfo.STATUSCHANGTIME]==-1){
									newInfo[DetectInfo.STATUSCHANGTIME]=
											newInfo[DetectInfo.CHECKTIME]==null?newInfo[DetectInfo.STARTTIME]:newInfo[DetectInfo.CHECKTIME];
								}
							}
							if(allDeteInfo.size()<2){
								insertDataTonew.addAll(allDeteInfo);
							}else{
								Collections.sort(allDeteInfo, new Comparator<Object[]>() {
									@Override
									public int compare(Object[] o1, Object[] o2) {
										Long time1 = (Long) o1[DetectInfo.CHECKTIME];
										Long time2 = (Long) o2[DetectInfo.CHECKTIME];
										return time1 < time2 ? -1 : 1;
									}
								});
								insertDataTonew.add(allDeteInfo.get(0));
								
							}
							
						}
					}
				}
			}
			sw.tag(l + "e");
			logger.debug("告警判断完成，耗时：" + U.StopWatch.toString(sw.between(l + "e", l + "s")) );
			
			
			// 入库
			saveToNew(insertDataTonew, 0);
			saveToNew(updateDataTonew, 1);
			logger.info("info_new table update success! data size : "+(insertDataTonew.size()+updateDataTonew.size()));
			saveInfo(params);
			sw.tag(l + "sa");
			logger.debug("入库完成，耗时：" + U.StopWatch.toString(sw.between(l + "sa", l + "e")) );
		} catch (Exception e) {
			logger.error("detect info save error", e);
		}
		sw.tag("e" + count);
		logger.info("批量保存info,耗时： " + U.StopWatch.toString(sw.between("e" + count, "s" + count)));
	}

	/**
	 * 保存
	 * 
	 * @param infoList
	 * @throws SQLException
	 */
	private void saveInfo(List<Object[]> infoList) throws SQLException {
		Object[] temInfo = null;
		try {
			int infoCount = infoList.size();
			int warnCount = 0;
			int emailCount = 0;
			Map<String,Long> statusChangeMap = U.newHashMap();
			boolean emailFlag = Constants.flag_email == 1;// 是否启用 email
			Iterator<Object[]> ite = infoList.iterator();
			while (ite.hasNext()) {
				temInfo = ite.next();
				// 计算 详细表的 外键 时间戳（10） + seqId（5）+ setId (3)，主要是为了使用 java 中long 类型
				String checkTime = temInfo[DetectInfo.CHECKTIME].toString();
				String setId = temInfo[DetectInfo.SETINFOID].toString();
				String seqId = temInfo[DetectInfo.SEQID].toString();
				String checkType = temInfo[DetectInfo.CHECKTYPE].toString();//监测类别
				String id = DetectInfo.computeId(checkTime, seqId, setId);
				
				
				
				Object[] infoParam = new Object[] { id, setId, (String) temInfo[DetectInfo.DSINFO],
						(String) temInfo[DetectInfo.PDATA], temInfo[DetectInfo.CURRENTTIMES] + "",
						temInfo[DetectInfo.STARTTIME] != null ? format.format(new Date((Long) temInfo[DetectInfo.STARTTIME])) : null,
 						temInfo[DetectInfo.DELAYTIME] + "",
 						temInfo[DetectInfo.NEXTCHECKTIME] != null ? format.format(new Date((Long) temInfo[DetectInfo.NEXTCHECKTIME])) : null,
						temInfo[DetectInfo.PLEVEL],
						temInfo[DetectInfo.CHECKTIME] != null? format.format(new Date((Long) temInfo[DetectInfo.CHECKTIME])) : null,
						temInfo[DetectInfo.ARRIVETIME] != null? format.format(new Date((Long) temInfo[DetectInfo.ARRIVETIME])) : null,
						temInfo[DetectInfo.STATE] , checkTime, temInfo[DetectInfo.ARRIVETIME] , seqId,
						temInfo[DetectInfo.URGENTLEVEL] ,
						temInfo[DetectInfo.STATUSCHANGTIME] != null ? format.format(new Date((Long) temInfo[DetectInfo.STATUSCHANGTIME])) : null,
						Common.SEQUENCE.get(DetectInfo.DETECTION_INFO)==null?null:Common.SEQUENCE.get(DetectInfo.DETECTION_INFO).incrementAndGet()};
				
				if(Common.SEQUENCE.get(DetectInfo.DETECTION_INFO)==null){
					infoParam=Arrays.copyOf(infoParam, infoParam.length-1);
				}
				if(infoStmt == null){
					infoStmt = conn.prepareStatement(DetectInfo.getInsertInfoSql());
					infoStmt.setQueryTimeout(Constants.DB_STATEMENT_EXECUTE_TIMEOUT);
				}
				addRecordToStatement(infoStmt, infoParam);
				infoCount ++;
				
				// 添加告警信息:告警信息=状态异常+状态改变+推迟入库的
				if ((Integer) temInfo[DetectInfo.STATE] != 1 || (Boolean) temInfo[DetectInfo.STATECHANGEFLAG]) {
					Object[] params = new Object[] { id, (String) temInfo[DetectInfo.SETINFOID],
							(String) temInfo[DetectInfo.DSINFO], (String) temInfo[DetectInfo.PDATA],
							temInfo[DetectInfo.CURRENTTIMES]  ,
							temInfo[DetectInfo.STARTTIME] != null ? format.format(new Date((Long) temInfo[DetectInfo.STARTTIME])) : null,
							temInfo[DetectInfo.DELAYTIME] ,
							temInfo[DetectInfo.NEXTCHECKTIME] != null ? format.format(new Date((Long) temInfo[DetectInfo.NEXTCHECKTIME])) : null,
							temInfo[DetectInfo.PLEVEL] ,
							temInfo[DetectInfo.CHECKTIME] != null ? format.format(new Date((Long) temInfo[DetectInfo.CHECKTIME])) : null,
							temInfo[DetectInfo.ARRIVETIME] != null ? format.format(new Date((Long) temInfo[DetectInfo.ARRIVETIME])) : null,
							temInfo[DetectInfo.STATE] , temInfo[DetectInfo.CHECKTIME] ,
							temInfo[DetectInfo.ARRIVETIME] , (String) temInfo[DetectInfo.SEQID],
							temInfo[DetectInfo.URGENTLEVEL]  };

					if(warnStmt == null){
						warnStmt = conn.prepareStatement(DetectInfo.getInsertWarningSql());
						warnStmt.setQueryTimeout(Constants.DB_STATEMENT_EXECUTE_TIMEOUT);
					}
					addRecordToStatement(warnStmt, params);
					warnCount++;
				}

				// 延迟监测数据追加告警信息
				if (temInfo[DetectInfo.APPENDWARNINGINFO] != null) {
					Object[] warningInfo = (Object[]) temInfo[DetectInfo.APPENDWARNINGINFO];
					Object[] params = new Object[] { warningInfo[DetectInfo.DETECTIONINFOID],
							(String) warningInfo[DetectInfo.SETINFOID], (String) warningInfo[DetectInfo.DSINFO],
							(String) warningInfo[DetectInfo.PDATA], warningInfo[DetectInfo.CURRENTTIMES] ,
							warningInfo[DetectInfo.STARTTIME] != null ? format.format(new Date((Long) temInfo[DetectInfo.STARTTIME])) : null,
							warningInfo[DetectInfo.DELAYTIME] ,
							warningInfo[DetectInfo.NEXTCHECKTIME] != null ? format.format(new Date((Long) temInfo[DetectInfo.NEXTCHECKTIME])) : null,
							warningInfo[DetectInfo.PLEVEL] ,
							warningInfo[DetectInfo.CHECKTIME] != null ? format.format(new Date((Long) temInfo[DetectInfo.CHECKTIME])) : null,
							warningInfo[DetectInfo.ARRIVETIME] != null ? format.format(new Date((Long) temInfo[DetectInfo.ARRIVETIME])) : null,
							warningInfo[DetectInfo.STATE] , warningInfo[DetectInfo.CHECKTIME] ,
							warningInfo[DetectInfo.ARRIVETIME] , warningInfo[DetectInfo.SEQID],
							warningInfo[DetectInfo.URGENTLEVEL] };
					if(warnStmt == null){
						warnStmt = conn.prepareStatement(DetectInfo.getInsertWarningSql());
						warnStmt.setQueryTimeout(Constants.DB_STATEMENT_EXECUTE_TIMEOUT);
					}
					addRecordToStatement(warnStmt, params);
					warnCount++;
				}

				// 添加邮件信息
				if (!emailFlag) {
					logger.info("邮件功能已关闭");
				} else {
					if ((Boolean) temInfo[DetectInfo.SENDEMAILFLAG]) {
						EmailInfo emailInfo = (EmailInfo) temInfo[DetectInfo.EMAILINFO];
						if (emailInfo != null) {
							if (setInfoEmail == null) {
								setInfoEmail = this.getDetecSetEmailListOf123();
							}
							if (seqIdEmail == null) {
								seqIdEmail = this.getDetecEmailListOf4();
							}
							if ((setInfoEmail == null || setInfoEmail.size() == 0)
									&& (seqIdEmail == null || seqIdEmail.size() == 0)) {
								logger.debug("未找到邮件地址！");
							} else {
								List<String> emailAddress = null;
								// 1.首先通过监测设置的map中查找
								if (setInfoEmail != null) {
									emailAddress = setInfoEmail.get(setId);
								}
								if (emailAddress == null) {
									emailAddress = seqIdEmail.get(seqId);
								}
								if (emailAddress != null && emailAddress.size() > 0) {
									for (String tempAddress : emailAddress) {
										if (StringUtils.isNotEmpty(tempAddress)) {
											Object[] params = new Object[] { tempAddress, emailInfo.getActionType(),
													emailInfo.getContent(), emailInfo.getSendFlag(),
													emailInfo.getActionIp(), emailInfo.getActionDate(),
													emailInfo.getActionDesc(), emailInfo.getSendLevel(),
													DateUtil.getCurrentTime() };

											if(emailStmt == null){
												emailStmt = conn.prepareStatement(DetectInfo.getInsertEmailSql());
												emailStmt.setQueryTimeout(Constants.DB_STATEMENT_EXECUTE_TIMEOUT);
											}
											addRecordToStatement(emailStmt, params);
											emailCount ++;
										}
									}
								}
							}
						}
					}
				}
				
				if(Constants.DETEC_NMSC_STR.equalsIgnoreCase(checkType)){
					long temChangeTime = (Long) temInfo[DetectInfo.STATUSCHANGTIME];
					if(temChangeTime > 0 ){
						Long l = statusChangeMap.get(seqId);
						if(l == null || temChangeTime > l){
							statusChangeMap.put(seqId, temChangeTime);
						}
					}
				}
				ite.remove();
			}
			if(infoCount >0){
				infoStmt.executeBatch();
			}
			if(warnCount >0){
				warnStmt.executeBatch();
			}
			if(emailCount >0){
				emailStmt.executeBatch();
			}
			
			if(statusChangeMap.size() > 0){
				if(statusChangeStmt == null){
					statusChangeStmt = conn.prepareStatement(DetectInfo.getUpdateStatusSql());
					statusChangeStmt.setQueryTimeout(Constants.DB_STATEMENT_EXECUTE_TIMEOUT);
				}
				Set<Entry<String,Long>> entrySet = statusChangeMap.entrySet();
				for(Entry<String,Long> en : entrySet){
					Object[] params = {en.getValue()!=null?format.format(new Date((Long)en.getValue())):null,en.getKey()};
					addRecordToStatement(statusChangeStmt, params);
				}
				statusChangeStmt.executeBatch();
			}
			
			warnUpdateStmt.executeBatch();//update warning
			
			conn.commit();
			logger.info("批量保存，info ：" + infoCount + " , warn : " + warnCount + " ,email : "+ emailCount);
		} catch (Exception e) {
			logger.error("info save error ,temInfo : "+Arrays.toString(temInfo) ,e);
			conn.rollback();
		}finally {
			if(infoStmt != null){
				infoStmt.clearBatch();
			}
			if(warnStmt != null){
				warnStmt.clearBatch();
			}
			if(emailStmt != null){
				emailStmt.clearBatch();
			}
			if(statusChangeStmt != null){
				statusChangeStmt.clearBatch();
			}
		}
	}

	private Map<String, List<String>> getDetecEmailListOf4() {
		Map<String,List<String>> result = new HashMap<String, List<String>>();
		try {
			StringBuilder sb = new StringBuilder();
			sb.append(" select distinct nt.seq_id ,xyj.email");
			sb.append("   from xt_yh_jbxx xyj ");
			sb.append("   left join xt_yh_js_index xyji ");
			sb.append("     on xyji.yhid = xyj.yhid ");
			sb.append("   left join xt_js_jbxx xjj ");
			sb.append("     on xjj.jsbh = xyji.jsbh ");
			sb.append("   left join gorup_system_table gst ");
			sb.append("     on gst.user_group_id = xjj.jsbh ");
			sb.append("   left join system_table st ");
			sb.append("     on st.system_id = gst.system_id ");
			sb.append("   left join node_table nt ");
			sb.append("     on nt.system_id = gst.system_id ");
			sb.append("   left join nodegroup_table ngt ");
			sb.append("     on ngt.group_id = nt.node_group_id ");
			sb.append("  where xyj.is_receiveemail = '0' ");
			sb.append("    and nt.node_state = 0 ");
			sb.append("    and ngt.is_valid = 1 ");
			sb.append("    and st.system_state = 0 ");
			sb.append("    and xjj.zxbz = 0 ");
			sb.append("    and xjj.type = 1 ");
			sb.append("    and xyj.zxbz = 0 ");
			List<Map<String, Object>> map1 = db.select(conn, sb.toString());
			if(map1 != null && map1.size()>0){
				List<String> tempList = null;
				String email = null;
				String seqId = null;
				for(Map<String,Object> temp : map1){
					seqId = (String)temp.get("seq_id");
					email = (String)temp.get("email");
					tempList = result.get(seqId);
					if(tempList == null){//第一次添加
						List<String> emailList = new ArrayList<String>();
						emailList.add(email);
						result.put(seqId, emailList);
					}else{
						tempList.add(email);
					}
					seqId = null;
					email = null;
					tempList = null;
				}
			}
		} catch (Exception e) {
			logger.debug("查询邮件列表失败",e);
		}
		return result;
	}

	private Map<String, List<String>> getDetecSetEmailListOf123() {
		Map<String,List<String>> result = new HashMap<String, List<String>>();
		StringBuilder sb = new StringBuilder();
		sb.append(" select distinct c.id, xyj1.email  ");
		sb.append(" from xt_yh_jbxx xyj1, ");
		sb.append("    (select dsi.id, ',' || dsi.contact_user_ids || ',' as ids ");
		sb.append("     from detection_set_info dsi ");
		sb.append("    where dsi.contact_user_ids is not null) c ");
		sb.append(" where  c.ids  like ('%,' || xyj1.yhid || ',%') ");
		sb.append(" and xyj1.email  is not null ");
		sb.append("  union  ");
		sb.append(" (select distinct dsi.id,xyj.email ");
		sb.append("   from detection_set_info dsi ");
		sb.append("   left join xt_js_jbxx xjj ");
		sb.append("     on dsi.create_usergroup_id = xjj.jsbh ");
		sb.append("   left join xt_yh_js_index xyji ");
		sb.append("     on xjj.jsbh = xyji.jsbh ");
		sb.append("   left join xt_yh_jbxx xyj ");
		sb.append("     on xyj.yhid = xyji.yhid ");
		sb.append("  where xyj.is_receiveemail = '0' ");
		sb.append("    and xjj.zxbz = 0 ");
		sb.append("    and xjj.type = 1 ");
		sb.append("    and xyj.zxbz = 0 ");
		sb.append("    and dsi.view_level = 2 ");
		sb.append("    and xyj.email is not null ");
		sb.append("    and dsi.create_usergroup_id is not null ");
		sb.append("    and dsi.contact_user_ids is null) ");
		sb.append(" union ");
		sb.append(" ( ");
		sb.append("    select distinct dsi.id,xyj.email from detection_set_info dsi ");
		sb.append("  left join gorup_system_table gst ");
		sb.append("    on gst.system_id = dsi.system_id ");
		sb.append("  left join xt_js_jbxx xjj  ");
		sb.append("  on gst.user_group_id = xjj.jsbh ");
		sb.append(" left join xt_yh_js_index xyji ");
		sb.append(" on xjj.jsbh = xyji.jsbh ");
		sb.append(" left join xt_yh_jbxx xyj ");
		sb.append(" on xyji.yhid = xyj.yhid ");
		sb.append(" where xyj.is_receiveemail = '0' ");
		sb.append("    and xjj.zxbz = 0 ");
		sb.append("    and xjj.type = 1 ");
		sb.append("    and xyj.zxbz = 0 ");
		sb.append("    and dsi.view_level = 3  ");
		sb.append("    and xyj.email is not null ");
		sb.append("    and dsi.contact_user_ids is null ");
		sb.append(" ) ");

		try {
			List<Map<String,Object>> map1 = db.select(conn, sb.toString());
			if(map1 != null && map1.size()>0){
				List<String> tempList = null;
				String email = null;
				String id = null;
				for(Map<String,Object> temp : map1){
					id = (String)temp.get("id");
					email = (String)temp.get("email");
					tempList = result.get(id);
					if(tempList == null){//第一次添加
						List<String> emailList = new ArrayList<String>();
						emailList.add(email);
						result.put(id, emailList);
					}else{
						tempList.add(email);
					}
					id = null;
					email = null;
					tempList = null;
				}
			}
		} catch (Exception e) {
			logger.debug("查询邮件列表失败",e);
		}
		return result;
	}

	/**
	 * 判断状态变更
	 * 
	 * @param allDeteInfo 单条监测设置id下的 监测数据
	 * @param oldDetecInfo	new表中对应监测设置id下的监测数据
	 */
	private void judgeStatus(List<Object[]> allDeteInfo, Object[] oldDetecInfo) {
		if (allDeteInfo.size() < 2) {// 只有一条数据直接比较数据库中的数据
			// 只有一条最新监测
			Object[] newDetecInfo = allDeteInfo.get(0);

			int state = (Integer) newDetecInfo[DetectInfo.STATE];
			/*
			 * 入库数据不是延时数据时，与数据库中的最新数据比对判断状态变更 数据库中的监测时间小于当前需要入库的监测时间
			 */
			if ((Long) oldDetecInfo[DetectInfo.CHECKTIME] < (Long) newDetecInfo[DetectInfo.CHECKTIME]) {
				/* 判断状态变更 */
				stateChange(newDetecInfo, oldDetecInfo);
			} else {// 监测时间小于数据库中监测数据的时间，说明当前需要入库的监测为延迟数据
				if (state != 1) {// 延迟数据监测状态没有成功，数据库入库的是正常数据，补录一条报警信息
					if ((Integer) newDetecInfo[DetectInfo.STATE] == 1
							&& (Integer) oldDetecInfo[DetectInfo.PLEVEL] == 99) {
						newDetecInfo[DetectInfo.APPENDWARNINGINFO] = oldDetecInfo;
					}
				}
			}
		} else {// 大于两条数据时，排序之后判断数据库的数据是否为最接近的时间数据
				// 未入库的数据排序
			Collections.sort(allDeteInfo, new Comparator<Object[]>() {
				@Override
				public int compare(Object[] o1, Object[] o2) {
					Long time1 = (Long) o1[DetectInfo.CHECKTIME];
					Long time2 = (Long) o2[DetectInfo.CHECKTIME];
					return time1 < time2 ? -1 : 1;
				}
			});
			/* 判断状态变更 */
			judgeState(allDeteInfo, oldDetecInfo);
		}
		
	}

	/**
	 * 整理 缓存中的 info 数据，方便 判断告警信息
	 * 
	 * @param params
	 * @return
	 */
	private Map<String, Map<String, List<Object[]>>> orderInfo(List<Object[]> params) {
		Map<String, Map<String, List<Object[]>>> result = U.newHashMap();
		// 先将所有的数据整理成 结果集合
		for (Object[] item : params) {
			String seqId = (String) item[DetectInfo.SEQID];
			String setId = (String) item[DetectInfo.SETINFOID];
			Map<String, List<Object[]>> setMap = result.get(seqId);
			if (setMap == null) {
				List<Object[]> l = U.newArrayList();
				l.add(item);
				setMap = U.newHashMap();
				setMap.put(setId, l);
				result.put(seqId, setMap);
			} else {
				List<Object[]> list = setMap.get(setId);
				if (list == null) {
					list = U.newArrayList();
					list.add(item);
					setMap.put(setId, list);
				} else {
					list.add(item);
				}
			}
		}
		// 将list排序
		if (result.size() > 0) {
			Set<Entry<String, Map<String, List<Object[]>>>> seqEn = result.entrySet();
			for (Entry<String, Map<String, List<Object[]>>> se : seqEn) {
				Map<String, List<Object[]>> setMap = se.getValue();
				Set<Entry<String, List<Object[]>>> setEn = setMap.entrySet();
				for (Entry<String, List<Object[]>> st : setEn) {
					List<Object[]> list = st.getValue();
					if (list.size() > 1) {
						// 统一seqid setid 的数据排序
						Collections.sort(list, new Comparator<Object[]>() {
							@Override
							public int compare(Object[] o1, Object[] o2) {
								if (o1 != null && o2 != null) {
									long l1 = (long) o1[DetectInfo.CHECKTIME];
									long l2 = (long) o2[DetectInfo.CHECKTIME];
									return l1 < l2 ? -1 : 1;
								}
								return 0;
							}
						});
					}
				}
			}
		}
		return result;
	}

	/**
	 * 查询 detection_info_new 表中的最新数据
	 * 
	 * @param seqId
	 * @return
	 */
	private Map<String, Map<String, Object[]>> getDetectNewData(Collection<String> seqId) {
		Map<String, Map<String, Object[]>> result = U.newHashMap();
		try {
			String seqIds = StringUtils.join(seqId.iterator(), ",");
			StringBuilder sbSql = new StringBuilder();
			sbSql.append(
					"select din.ID,din.DETECTION_SET_INFO_ID,din.CHECK_WAY,din.DETECTION_STATE_INFO,din.PERFORMACE_DATA,din.CURRENT_TIMES,din.START_TIME,din.WAIT_TIME,din.DELAY_TIME,din.NEXT_CHECK_TIME,din.OFF_LINE,din.POLICE_LEVEL,din.DATA_CHECK_TIME,din.DATA_ARRIVE_TIME,din.DETECTIONED_STATE,din.NODE_IP,din.STATUS_CHANGE_TIME,din.DATA_CHECK_TIME_DIGITAL,din.DATA_ARRIVE_TIME_DIGITAL,din.SEQ_ID,din.DETECTION_INFO_ID,din.VALID,din.POLICE_EMERGENT");
			sbSql.append(" from detection_info_new din ");
			sbSql.append(" where  ");
			sbSql.append(" din.seq_id in ( ");
			sbSql.append(seqIds);
			sbSql.append(" )");
			String sql = sbSql.toString();
			List<Map<String, Object>> list = db.select(conn,sql);
			if (list != null) {
				for (Map<String, Object> item : list) {
					Object[] obj = new Object[33];
					String seq = item.get("SEQ_ID").toString();
					String setId = item.get("DETECTION_SET_INFO_ID").toString();
					obj[DetectInfo.SETINFOID] = setId;
					obj[DetectInfo.SEQID] = seq;
					obj[DetectInfo.STATE] = (item.get("DETECTIONED_STATE") == null ? null
							: Integer.parseInt(item.get("DETECTIONED_STATE").toString()));
					obj[DetectInfo.CHECKTIME] = (item.get("DATA_CHECK_TIME_DIGITAL") == null ? null
							: Long.parseLong(item.get("DATA_CHECK_TIME_DIGITAL").toString()));
					obj[DetectInfo.PLEVEL] = (item.get("POLICE_LEVEL") == null ? -1
							: Integer.parseInt(item.get("POLICE_LEVEL").toString()));
					obj[DetectInfo.URGENTLEVEL] = (item.get("POLICE_EMERGENT") == null ? -1
							: Integer.parseInt(item.get("POLICE_EMERGENT").toString()));
					obj[DetectInfo.DETECTIONINFOID] = (item.get("DETECTION_INFO_ID"));
					obj[DetectInfo.STATUSCHANGTIME] = (item.get("STATUS_CHANGE_TIME") == null ? null
							: ((Date) item.get("STATUS_CHANGE_TIME")).getTime());
					obj[DetectInfo.ARRIVETIME] = (item.get("DATA_ARRIVE_TIME_DIGITAL") == null ? null
							: Long.parseLong(item.get("DATA_ARRIVE_TIME_DIGITAL").toString()));
					obj[DetectInfo.DELAYTIME] = (item.get("DELAY_TIME") == null ? null
							: Integer.parseInt(item.get("DELAY_TIME").toString()));
					obj[DetectInfo.NEXTCHECKTIME] = (item.get("NEXT_CHECK_TIME") == null ? null
							: ((Date) item.get("NEXT_CHECK_TIME")).getTime());
					obj[DetectInfo.STARTTIME] = (item.get("START_TIME") == null ? null
							: ((Date) item.get("START_TIME")).getTime());
					obj[DetectInfo.DSINFO] = (item.get("DETECTION_STATE_INFO"));
					obj[DetectInfo.PDATA] = (item.get("PERFORMACE_DATA"));
					obj[DetectInfo.CURRENTTIMES] = (item.get("CURRENT_TIMES") == null ? -1
							: Integer.parseInt(item.get("CURRENT_TIMES").toString()));

					// 将数据库中的最新数据组织成 seqId setId data
					Map<String, Object[]> map = result.get(seq);
					if (map == null) {
						map = U.newHashMap();
						map.put(setId, obj);
						result.put(seq, map);
					} else {
						map.put(setId, obj);
					}
				}
				return result;
			}
		} catch (Exception e) {
			logger.warn("select detection_info_new error", e);
		}
		return result;
	}

	/**
	 * 判断状态变更具体实现
	 * 
	 * @param newDetecInfo 准备入库数据
	 *           
	 * @param oldDetecInfo new表中的数据
	 */
	private void stateChange(Object[] newDetecInfo, Object[] oldDetecInfo) {
		/**
		 * 判断状态变更
		 */
		if (newDetecInfo == null || oldDetecInfo == null
				|| ((Long) newDetecInfo[DetectInfo.CHECKTIME] < (Long) oldDetecInfo[DetectInfo.CHECKTIME])) {
			return;
		}
		if (((Integer) oldDetecInfo[DetectInfo.STATE] != (Integer) newDetecInfo[DetectInfo.STATE]) || // 状态改变
				(((Integer) oldDetecInfo[DetectInfo.STATE] == (Integer) newDetecInfo[DetectInfo.STATE]
						&& (Integer) oldDetecInfo[DetectInfo.PLEVEL] != (Integer) newDetecInfo[DetectInfo.PLEVEL]))) {// 状态未变，告警级别改变

			int state = (Integer) newDetecInfo[DetectInfo.STATE];
			// 邮件告警信息
			StringBuffer alarmInfo = new StringBuffer((String) newDetecInfo[DetectInfo.ALARMINFO]);// 告警信息
			String dsinfo = (String) newDetecInfo[DetectInfo.DSINFO];// 状态信息
			String checkType = (String) newDetecInfo[DetectInfo.CHECKTYPE];// 监测类别
			long checkTime = (Long) newDetecInfo[DetectInfo.CHECKTIME];
			int actionType = 11;
			int urgentLevel = EmailTypeConstants.URGENT_LATER;
			// 整理告警数据,拼写邮件信息
			if (state == -1) { // 执行失败
				// alarmInfo.append("监测执行失败\n ");
				// alarmInfo.append("Failure to monitor execution\n ");
				alarmInfo.append("i18n_server.DetecDataResoveThread.alarmInfo1_n81i\n  ");
				alarmInfo.append(dsinfo + "\n");
				actionType = EmailTypeConstants.TYPE_DETECTION_INFO_EXCEPTION;
				if (Constants.DETEC_NMSC_STR.equalsIgnoreCase(checkType)) {
					urgentLevel = EmailTypeConstants.URGENT_IMMEDIATELY;

				}
			} else if (state == 0) { // 一般异常
				alarmInfo.append("  " + dsinfo + "\n");
				// 如果是握手监测，不添加告警设置字段相关信息
				if (!Constants.DETEC_NMSC_STR.equalsIgnoreCase(checkType)) {
					alarmInfo.append(dsinfo + " \n");
				} else {
					alarmInfo.delete(0, alarmInfo.length());// 如果是握手监测，则不添加告警设置字段相关信息
					alarmInfo.append(dsinfo + " \n");
					urgentLevel = EmailTypeConstants.URGENT_IMMEDIATELY;
				}
				actionType = EmailTypeConstants.TYPE_DETECTION_INFO_EXCEPTION;
			} else if (state == 1) { // 恢复正常
				// alarmInfo.append("监测恢复正常");
				// alarmInfo.append("Monitoring back to normal");
				alarmInfo.append("i18n_server.DetecDataResoveThread.alarmInfo1_n81i");
				actionType = EmailTypeConstants.TYPE_DETECTION_INFO_RECOVER;
				urgentLevel = EmailTypeConstants.URGENT_LATER;
				// 更新该节点所有监测时间为当前监测时间
				if (checkType.equalsIgnoreCase(Constants.DETEC_NMSC_STR)) {
					newDetecInfo[DetectInfo.STATUSCHANGTIME] = (checkTime);
				}
//				//update warning table
//				collectWarnUpdateInfo(newDetecInfo);
			}
			// 报警通知

			newDetecInfo[DetectInfo.STATECHANGEFLAG] = (true);
			newDetecInfo[DetectInfo.ALARMINFO] = (alarmInfo.toString());
			newDetecInfo[DetectInfo.SENDEMAILFLAG] = (true);
			newDetecInfo[DetectInfo.URGENTLEVEL] = (urgentLevel);
			// 目前代码中是否紧急和紧急级别不对应，有的是紧急，但是级别是2，所以此处进行修改，如果是紧急，则级别修改为0级
			if (EmailTypeConstants.URGENT_IMMEDIATELY == urgentLevel) {
				newDetecInfo[DetectInfo.PLEVEL] = Constants.LEVEL_OF_EMERGENCY;
			}
			// 如果是0级，则设置为紧急，使得紧急状态和级别一致
			if (newDetecInfo[DetectInfo.PLEVEL].equals(Constants.LEVEL_OF_EMERGENCY)) {
				newDetecInfo[DetectInfo.URGENTLEVEL] = EmailTypeConstants.URGENT_IMMEDIATELY;
			}
			long seqIdLong = Long.parseLong((String) newDetecInfo[DetectInfo.SEQID]);
			long setInfoIdLong = Long.parseLong((String) newDetecInfo[DetectInfo.SETINFOID]);

			String emailContent = alarmInfo.toString();
			if (emailContent.getBytes().length > 290) {
				emailContent = StringUtil.substring(emailContent, 290);
			}
			EmailInfo emailInfo = new EmailInfo(actionType,
					Common.getSetInfoNameMape().get(setInfoIdLong) + "(" + Common.getCheckTypeNameMape().get(checkType)
							+ ")",
					Common.getNodeIpByUUID(seqIdLong), format.format(new Date(checkTime)), emailContent,
					EmailTypeConstants.FLAG_SEND_LATER, urgentLevel);
			newDetecInfo[DetectInfo.EMAILINFO] = (emailInfo);
			
			
			//如果新入数据和new表中的监测状态不同，或者监测状态相同，告警级别不同   ，修改  状态改变时间 为获取新入数据的时间（data_check_time）
			newDetecInfo[DetectInfo.STATUSCHANGTIME]=newDetecInfo[DetectInfo.CHECKTIME];
		}
		else{//如果新入数据和new表中的监测状态相同，且告警级别相同  ，则状态改变时间更新为new表中的时间
			newDetecInfo[DetectInfo.STATUSCHANGTIME]=oldDetecInfo[DetectInfo.STATUSCHANGTIME];
		}
		
		
		
	}

	/**
	 * 状态变更判断:只对大于等于new表监测时间的监测数据进行是否告警的判断
	 * 
	 * @param allDetectInfo
	 * @param inDbInfo
	 */
	private void judgeState(List<Object[]> allDetectInfo, Object[] inDbInfo) {
		/*
		 * 判断每一个的状态变更 1.监测时间小于已经入库的监测数据时间不做判断
		 */
		int startIndex = 0;
		for (int i = 0, j = allDetectInfo.size(); i < j; i++) {
			Object[] newDetecInfo = allDetectInfo.get(i);
			Object[] oldDetecInfo = null;// 前一条监测数据
			// 监测时间小于已经入库的监测数据时间不做判断，只在最后一条数据判断插入告警信息
			if (newDetecInfo == null
					|| (Long) newDetecInfo[DetectInfo.CHECKTIME] < (Long) inDbInfo[DetectInfo.CHECKTIME]) {
				startIndex++;
				if (i < j - 1) {
					continue;
				} else {
					// 集合中的最后一条数据监测时间也小于数据库中的时间时，最后一条数据判断是否插入一条告警信息
					if ((Integer) newDetecInfo[DetectInfo.STATE] != 1) {// 延迟数据监测状态没有成功，数据库入库的是正常数据，补录一条报警信息
						if ((Integer) inDbInfo[DetectInfo.STATE] == 1 && (Integer) inDbInfo[DetectInfo.PLEVEL] == 99) {
							newDetecInfo[DetectInfo.APPENDWARNINGINFO] = oldDetecInfo;
						}
					}
				}
			}
			// 判断最新的监测数据
			if (i == startIndex) {
				oldDetecInfo = inDbInfo;
			} else {
				oldDetecInfo = allDetectInfo.get(i - 1);
			}
			/* 判断状态变更 */
			stateChange(newDetecInfo, oldDetecInfo);
		}
	}

	/**
	 * stmt addbatch
	 * @param stmt
	 * @param params
	 * @throws SQLException
	 */
	private void addRecordToStatement(PreparedStatement stmt, Object[] params) throws SQLException {
		if (params != null) {
			logger.debug(" params " + Arrays.toString(params));
			for (int i = 0; i < params.length; i++) {
				stmt.setObject(i + 1, params[i]);
			}
			stmt.addBatch();
		}
	}
	
	/**
	 * @param allDeteInfo 
	 * @param oldDetecInfo
	 * @param newDataList
	 */
	private void judgeAndCollect(List<Object[]> allDeteInfo, Object[] oldDetecInfo,List<Object[]> newDataList){
		Object[] newDeteInfo = allDeteInfo.get(0);
		if((Long)newDeteInfo[DetectInfo.CHECKTIME]>(Long)oldDetecInfo[DetectInfo.CHECKTIME]){
				newDataList.add(newDeteInfo);
		}
		if((Integer)newDeteInfo[DetectInfo.STATE]==1){
				Object[] params={newDeteInfo[DetectInfo.SEQID],newDeteInfo[DetectInfo.SETINFOID]};
				try {
					addRecordToStatement(warnUpdateStmt, params);
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
		}
	}
	
	private void saveToNew(List<Object[]> dataList,int flag){
		if(dataList!=null&&dataList.size()>0){
			if(flag==0){//insert
				String sql=DetectInfo.getSaveToNewSql();
				try {
					infoNewInsertStmt=conn.prepareStatement(sql);
					for (Object[] newData : dataList) {
						// 计算 详细表的 外键 时间戳（10） + seqId（5）+ setId (3)，主要是为了使用 java 中long 类型
						String checkTime = newData[DetectInfo.CHECKTIME].toString();
						String setId = newData[DetectInfo.SETINFOID].toString();
						String seqId = newData[DetectInfo.SEQID].toString();
						String id = DetectInfo.computeId(checkTime, seqId, setId);
						Object []params={
								newData[DetectInfo.SETINFOID],
								newData[DetectInfo.DSINFO],
								newData[DetectInfo.PDATA],
								newData[DetectInfo.CURRENTTIMES],
								newData[DetectInfo.STARTTIME] != null ? format.format(new Date((Long) newData[DetectInfo.STARTTIME])) : null,
								newData[DetectInfo.WAITTIME],
								newData[DetectInfo.DELAYTIME],
								newData[DetectInfo.NEXTCHECKTIME]!= null ? format.format(new Date((Long) newData[DetectInfo.NEXTCHECKTIME])) : null,
								newData[DetectInfo.PLEVEL],
								newData[DetectInfo.CHECKTIME]!= null ? format.format(new Date((Long) newData[DetectInfo.CHECKTIME])) : null,
								newData[DetectInfo.ARRIVETIME]!= null ? format.format(new Date((Long) newData[DetectInfo.ARRIVETIME])) : null,
								newData[DetectInfo.STATE],
								newData[DetectInfo.STATUSCHANGTIME]!= null ? format.format(new Date((Long) newData[DetectInfo.STATUSCHANGTIME])) : null,
								newData[DetectInfo.SEQID],
								id,
								newData[DetectInfo.CHECKTIME],
								newData[DetectInfo.ARRIVETIME],
								newData[DetectInfo.URGENTLEVEL]
						};
						addRecordToStatement(infoNewInsertStmt, params);
					}
					infoNewInsertStmt.executeBatch();
					logger.info("info_new table insert success! size : "+ dataList.size());
				} catch (SQLException e) {
					logger.error("save info to info_new table error"+e.getMessage());
				}
			}else if(flag==1){//update
				String sql=DetectInfo.getUpdateToNewSql();
				try {
					infoNewUpdateStmt=conn.prepareStatement(sql);
					for (Object[] newData : dataList) {
						// 计算 详细表的 外键 时间戳（10） + seqId（5）+ setId (3)，主要是为了使用 java 中long 类型
						String checkTime = newData[DetectInfo.CHECKTIME].toString();
						String setId = newData[DetectInfo.SETINFOID].toString();
						String seqId = newData[DetectInfo.SEQID].toString();
						String id = DetectInfo.computeId(checkTime, seqId, setId);
						Object []params={newData[DetectInfo.DSINFO],
								newData[DetectInfo.PDATA],
								newData[DetectInfo.CURRENTTIMES],
								newData[DetectInfo.STARTTIME] != null ? format.format(new Date((Long) newData[DetectInfo.STARTTIME])) : null,
								newData[DetectInfo.WAITTIME],
								newData[DetectInfo.DELAYTIME],
								newData[DetectInfo.NEXTCHECKTIME]!= null ? format.format(new Date((Long) newData[DetectInfo.NEXTCHECKTIME])) : null,
								newData[DetectInfo.PLEVEL],
								newData[DetectInfo.CHECKTIME]!= null ? format.format(new Date((Long) newData[DetectInfo.CHECKTIME])) : null,
								newData[DetectInfo.ARRIVETIME]!= null ? format.format(new Date((Long) newData[DetectInfo.ARRIVETIME])) : null,
								newData[DetectInfo.STATE],
								newData[DetectInfo.STATUSCHANGTIME]!= null && (Long)newData[DetectInfo.STATUSCHANGTIME]!= -1? format.format(new Date((Long) newData[DetectInfo.STATUSCHANGTIME])) : null,
								id,	
								newData[DetectInfo.CHECKTIME],
								newData[DetectInfo.ARRIVETIME],
								newData[DetectInfo.URGENTLEVEL],
								newData[DetectInfo.SETINFOID],
								newData[DetectInfo.SEQID]
						};
						addRecordToStatement(infoNewUpdateStmt, params);
					}
					infoNewUpdateStmt.executeBatch();
					logger.info("info_new table update success! size : "+ dataList.size());
				} catch (SQLException e) {
					logger.error("update info to info_new table error"+e.getMessage());
				}
			}
			dataList.clear();
		}
	}
	private void collectWarnUpdateInfo(Object[] newDetectInfo){
		Object[] params={newDetectInfo[DetectInfo.SEQID],newDetectInfo[DetectInfo.SETINFOID]};
		try {
			addRecordToStatement(warnUpdateStmt, params);
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
}
