package com.nms.server.thread.alarmData;

import java.io.File;
import java.util.Calendar;
import java.util.LinkedList;
import java.util.concurrent.Future;

import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;

import com.nms.server.common.Common;
import com.nms.server.common.Constants;
import com.nms.server.dao.CommonDao;
import com.nms.server.util.ExceptionPrintUtils;
import com.nms.server.util.StringUtil;

public class AlarmDataResoveManagerThread implements Runnable{
	private Logger logger = Logger.getLogger(AlarmDataResoveManagerThread.class);
	private int testNum = 0;//尝试运行线程Constants.ALARM_DATA_RESOVE的次数
	
	public void run() {
//		Thread.currentThread().setName("告警数据解析管理线程");
		Thread.currentThread().setName("Alarm Data Parsing Management Threads");
		//将线程运行程序，尽可能的catch捕获异常
		try {
			boolean runFlag = Common.isDbConnected();//测试数据库连接
			
			//- 检查线程运行状态
			Future<?> future = Common.getFutureMap().get(Constants.ALARM_DATA_RESOVE);
			if(future != null && !future.isCancelled() && !future.isDone() && runFlag){	//运行中
				runFlag = false;
				logger.info("告警解析 运行中 不再启动");
			}
			
			/*
			 * 连续超过Constants.CHECK_WARNING_DATA_OVERRUN次数时，将数据存入硬盘中
			 * 否则 正常执行数据解析线程
			 * */
			if(!runFlag){	//判断并结束线程
				testNum = (testNum%Constants.CHECK_WARNING_DATA_OVERRUN);
				testNum++;
				if(testNum==Constants.CHECK_WARNING_DATA_OVERRUN) {
					if(Constants.FLAG_WARN_DATA_SAVE_DISK_RESOVE==1) {
						/*
						 * 连续多个周期仍未解析完成
						 * 说明list里存有大量的数据，则先将当前未解析的数据列表存入硬盘，
						 * 然后停掉解析线程，将正在解析的数据列表中的剩余数据存入硬盘
						 * */
						logger.warn("Create a database connection failure data to write to the hard disk");
						saveWarningDataToDisk();
					}
				}
				return;
			}else{		//重置计数器 程序继续执行
				testNum = 1;
			}
		
			
			//- 非升级操作判断
			if(Common.SERVER_UN_UPGRADE_FLAG){
				
				//-- 启动新解析线程
				//-- 变更存储区 
				Common.changeAlarmDataFlag();	//变更数据存放集合
				
				LinkedList<String []> adList =  Common.getAlarmDataList();	// 获取非存放状态的数据集合
				if(adList != null && adList.size()>0){
					logger.info("告警解析 空闲中 启动");
//					future = Common.service.submit(new AlarmDataResoveThread("告警解析",adList));
					future = Common.service.submit(new AlarmDataResoveThread("Alarm Parsing",adList));
					//注册 告警线程
					Common.getFutureMap().put(Constants.ALARM_DATA_RESOVE, future);
				}else{
					logger.info("告警数据为0，解析结束");
				}
			}

		} catch (Exception e) {
			logger.error("Running exception",e);
		}
	}
	
	/**
	 * 数据库是否可连接判断
	 * @time Mar 7, 2013-2:22:42 PM
	 * @return
	 */
	public boolean dbTest() {
		CommonDao dao = null;
		try {
//			if(!false)throw new Exception("强制异常");
			dao = new CommonDao();
			logger.debug("尝试获取数据库连接成功");
			return true;
		} catch (Exception e) {
			logger.error("Try to get a database connection failure", e);
			/* 告警 */
			return false;
		}finally{
			if(dao!=null){
				dao.close();
				dao=null;
			}
		}
	}
	
    //2013-2-19 hyx ：当告警数据量过大时，将数据先存放到硬盘，再定时入库（由单独的定时线程实现）
	public void saveWarningDataToDisk() {
		LinkedList<String []> notResolvingWarningDataList =  Common.getNotResovlingWarnDataList();	// 获取未在解析的告警数据集合
		try {
			
			//终止正在解析告警数据的线程，并将正在解析的list里未解析的数据存入硬盘
			Future<?> future = Common.getFutureMap().get(Constants.ALARM_DATA_RESOVE);
			if(future != null && !future.isCancelled() && !future.isDone()){	//运行中
				future.cancel(true);
			}
			LinkedList<String []> warningDataList = Common.getAlarmDataList();	// 获取非存放状态的数据集合(正在解析的list)
			saveStrToFile(warningDataList);
			
			//将未在解析的list存放到硬盘上
			saveStrToFile(notResolvingWarningDataList);
			
			
		}catch(IndexOutOfBoundsException e) {
			logger.error("When the alarm data is too much, the data is stored in the hard disk",e);
		}catch (Exception e) {
			logger.error(ExceptionPrintUtils.printExceptionStack(e));
		}
			
	}
	
	private void saveStrToFile(LinkedList<String[]> dataList) {
		String filePath = "";
		int dataSize = dataList.size();//如果不按此时的size来操作，则list里的数据可能会一直在增加，就会一直循环下去？
		logger.info("告警数据过多，共"+dataSize+"条告警数据，等待存入硬盘");
		try {
			for(int j=0;j<dataSize;j++) {
				if(dataList.size()>0) {
					String[] data= dataList.get(0);
					filePath = Constants.OVERRUN_WARNING_FILE_DIR+"/"+Common.getDateDirName()+"/"+Calendar.getInstance().getTimeInMillis()+"_"+j+".csv";
					File file = new File(filePath);
					String dataStr = StringUtil.linkToString(data, Constants.COMMON_DATA_SPLIT, "");
					FileUtils.writeStringToFile(file, dataStr);
//				String[] msg = FileUtils.readFileToString(file).split(Constants.COMMON_DATA_SPLIT);
//				System.out.println(FileUtils.readFileToString(file));
					dataList.remove(0);
					logger.info("告警数据过多，已保存至"+filePath);
					
				}
			}
			
		}catch(Exception e) {
			logger.error("When the alarm data is too much, the data is stored in the hard disk",e);
		}
	}
	
	public static void main(String[] args) {
		String [] alarms = {"1","2","3","4"};
		String [] alarms2 = {"21","2","3","4"};
		String [] alarms3 = {"31","2","3","4"};
		Common.addAlarmData(alarms);
		Common.addAlarmData(alarms2);
		Common.changeAlarmDataFlag();
		Common.addAlarmData(alarms3);
		new AlarmDataResoveManagerThread().saveWarningDataToDisk();
	}
}
