package com.nms.server.thread.detectDataHandler;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Queue;
import java.util.Set;

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.common.Common;
import com.nms.server.common.Constants;
import com.nms.server.util.DateUtil;
/**
 * 监测详细数据入库线程
 * @author dell
 *
 */
@SuppressWarnings("all")
public class DetectDetailInsertThread implements Runnable{
	private static final Logger logger = Logger.getLogger(DetectDetailInsertThread.class);
	private static Db db = Common.getDb();
	private StopWatch sw = null;
	private Connection conn = null;
	private String key;
	private List<Map<String,String>> data;
	
	public DetectDetailInsertThread(String key,List<Map<String,String>> data) {
		this.key = key;
		this.data = data;
	}
	
	
	@Override
	public void run() {
		Thread.currentThread().setName("DetectDetailInsertThread-"+key);
		logger.info("开始运行->" + key);
		sw = U.StopWatch.newStopWacth();
		sw.start();//开始计时
		try {
			conn = db.getConnection();
			saveData(key,data);
			//遍历 监测数据等待入库 table
			/*Hashtable<String, Queue> hb = Common.DETECT_QUEUE;
			Set<Entry<String, Queue>> es = hb.entrySet();
			Iterator<Entry<String, Queue>> ite = es.iterator();
			while(ite.hasNext() && ! Common.isStop() && ! Thread.currentThread().isInterrupted() ){
				Entry<String, Queue> next = ite.next();
				String key = next.getKey();
				if(DetectInfo.INFO_KEY.equalsIgnoreCase(key)){
					//info 表的数据此线程不做解析
					continue;
				}
				Queue<Map<String,String>> data = next.getValue();
				saveData(key,data);
			}*/
			sw.end();
			
		} catch (Exception e) {
			logger.error("",e);
		} finally {
			db.closeQuiet(conn);
		}
		logger.info(key+ " 监测数据详细信息解析入库，耗时： " + U.StopWatch.toString(sw.total()));
		logger.info("结束运行->" + key);
		sw = null;
	}

	/**
	 * 保存详细监测数据
	 * @param data
	 */
	public void saveData(String checkType ,List<Map<String,String>> data){
		logger.info("监测类别：" + checkType +" 开始入库");
		sw.tag(checkType + "-start");
		int count = 0;
		PreparedStatement stmt = null;
		try {
			Map<String,String> ele = null;
			//详细信息对应的表名
			String detailTableName = null;
			if(DetectInfo.NET_STR_KEY.equalsIgnoreCase(checkType)){
				//系统信息-网卡信息
				detailTableName = "di_systeminfo_net";
			}else if(DetectInfo.DISK_STR_KEY.equalsIgnoreCase(checkType)){
				//系统信息-磁盘信息
				detailTableName = "di_systeminfo_disk";
			}else{
				detailTableName = Common.getInsertTable().get(checkType) == null ? null : Common.getInsertTable().get(checkType).getTableName();
			}
			
			if(detailTableName == null){
				logger.error(checkType + " the corresponding detailed table was not found and the data could not be stored");
				return;
			}
			List<Object[]> params = new LinkedList<Object[]>();//等待批处理参数
			List<String> fieldNames = new ArrayList<String>();//保存监测数据的字段
			String sql = null;//insert sql
			Iterator<Map<String, String>> ite = data.iterator();
			while( ite.hasNext()){
				ele = ite.next();
				count ++;
				if(sql == null){
					sql = DetectInfo.createDetailSql(fieldNames, detailTableName, ele);
					stmt = conn.prepareStatement(sql);
				}
				
				//计算 详细表的 外键     时间戳（10） + seqId（5）+ setId (3)，主要是为了使用 java 中long 类型
				String checkTime = ele.get("DATA_CHECK_TIME_DIGITAL");
				String setId = ele.get("DETECTION_SET_INFO_ID");
				String seqId = ele.get("SEQ_ID");
				String id = DetectInfo.computeId(checkTime, seqId, setId);
				ele.put("DETECTION_INFO_ID", id);
				
				Object[] detail = mapToArray(fieldNames, ele);
				params.add(detail);
				if(count % Constants.BATCH_RESOVE_COUNT == 0){
					//保存到数据库
					saveToDb(params, checkType, stmt);
					params.clear();
				}
			}
			if(params.size() > 0){
				//保存到数据库
				saveToDb(params, checkType, stmt);
				params.clear();
			}
		} catch (Exception e) {
			logger.error("save detect detail error ",e);
		}finally {
			db.closeQuiet(stmt);
		}
		sw.tag(checkType + "-end");
		logger.info("监测类别： " + checkType + " , 耗时： " + U.StopWatch.toString(sw.between(checkType+"-end",checkType+"-start")) +" ,共  " + count +"条");
	}
	
	/**
	 * 保存到数据库
	 * @param params
	 * @param checkType
	 * @param sql
	 */
	
	private void saveToDb(List<Object[]> params,String checkType,PreparedStatement	stmt){
		Object temp=null;
		Object[] arrTemp=null;
		long n = System.currentTimeMillis();
		sw.tag(n+"start");
		try {
			if (params != null && params.size() >0) {
				conn.setAutoCommit(false);
				int count=0;
				for(Object[] e : params){
					arrTemp=e;
					logger.debug(" params " + Arrays.toString(e)+"addToBatch ："+ ++count);
					for (int i = 0; i < e.length; i++) {
						Object value = e[i];
						temp=value;
						if(DateUtil.isDate((String)value, Constants.COMMON_DATE_FORMAT)){
							String str_format=(String)value;
							Date parse = new SimpleDateFormat(Constants.COMMON_DATE_FORMAT).parse(str_format);
							long time = parse.getTime();
							Timestamp timestamp = new Timestamp(time);
							stmt.setTimestamp(i+1,timestamp);
//							stmt.setTimestamp(i+1, new Timestamp(Common.getFormat().parse((String)value).getTime()));
						}else{
							stmt.setObject(i + 1, value);
						}
					}
					stmt.addBatch();
				}
				stmt.executeBatch();
				conn.commit();
				stmt.clearBatch();
			}
		} catch (Exception e) {
			try {
				conn.rollback();
			} catch (SQLException e1) {
			}
			logger.error("",e);
		}
		sw.tag(n+"end");
		logger.info("批量保存，类型 ：" + checkType + " , 共  " + params.size() +" 条" + " , 耗时： " + U.StopWatch.toString(sw.between(n+"end",n+"start")));
	}
	
	/**
	 * 将map组织成 数据，方便executeBatch
	 * 下一步（可以直接在解析的时候将数据解析成数组）
	 * @param fieldNames
	 * @param data
	 * @return
	 */
	private Object[] mapToArray(List<String> fieldNames,Map<String,String> data){
		int size = fieldNames.size();
		Object[] result = new Object[size];
		for(int i = 0;i<size;i++){
			String name = fieldNames.get(i);
			String value = data.get(name);
			result[i] = value;
		}
		return result;
	}
}
