package com.nms.server.thread.change;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;

import net.sf.json.JSONObject;

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

import com.nms.server.bean.AlarmInfo;
import com.nms.server.bean.NodeModel;
import com.nms.server.bean.SetInfo;
import com.nms.server.common.Common;
import com.nms.server.common.Constants;
import com.nms.server.dao.CommonDao;
import com.nms.server.service.ChangeService;
import com.nms.server.service.CommonService;
import com.nms.server.service.ThreadService;
import com.nms.server.thread.change.socket.ChangeSocketThread;

/**
 *  监测设置信息变更时
 *  通过新旧设置信息的对别，判断并更新
 *  其影响的所有的节点的监测设置
 *  （通讯不成功的监测设置通讯，保存入库，后续）
 *  @date Dec 27, 2011 2:57:35 PM
 *	@author ZhangGang
 */
public class ChangeForSetInfo implements Runnable{
	private final Logger logger = Logger.getLogger(ChangeForSetInfo.class);
	private String datas;
	private Long recordId;
	/**
	 * @param o SetInfo old监测设置信息
	 * @param n SetInfo new监测设置信息
	 */
	public ChangeForSetInfo(Long recordId,String datas){
		this.recordId = recordId;
		this.datas = datas;
	}

	public void run() {
//		Thread.currentThread().setName("监测设置变更");
		Thread.currentThread().setName("Monitoring Settings Change");
		
		JSONObject jObject = JSONObject.fromObject(datas);
		SetInfo o = (SetInfo) JSONObject.toBean(jObject.getJSONObject("old"), SetInfo.class);
		SetInfo n = (SetInfo) JSONObject.toBean(jObject.getJSONObject("new"), SetInfo.class);
//		logger.debug("old checktypename "+o.getCheckTypeName());
//		logger.debug("new checktypename "+n.getCheckTypeName());
		CommonDao dao = null;
		 
		try {
			dao = new CommonDao();
			ChangeService service = new ChangeService(dao);
			
			if(n == null){
				logger.warn("Monitoring settings to change invalid data："+jObject.toString());
				if(recordId!=null){
					service.deleteEventRecordByIds(recordId.toString());
				}
				return ;
			}
	    	/**old 与 new的节点组和节点的变化，影响该设置的监测变更范围
	    	 * old 与 new的监测状态有效性的变化，影响的是监测设置是否执行
	    	 * */
	    	boolean flag = true;
	    	//-- 监测范围变更校验
	    	if(o==null){	//新增监测：告警设置时，0=null
	    		flag = true;
	    	}else{	//修改
	    		String oldGIds = StringUtils.isBlank(o.getNodeGroupsId())?"0":o.getNodeGroupsId(); 
	    		String newGIds = StringUtils.isBlank(n.getNodeGroupsId())?"0":n.getNodeGroupsId(); 
	    		if(oldGIds.equals(newGIds)){	//节点组相等
	    			String oldNIPs = StringUtils.isBlank(o.getNodeIpsId())?"": o.getNodeIpsId(); 
	    			String newNIPs = StringUtils.isBlank(n.getNodeIpsId())?"": n.getNodeIpsId(); 
	    			if(oldNIPs.equals(newNIPs)){	//节点IP相等
	    				flag = true;
	    			}else{
	    				flag = false;
	    			}
	    		}else{
	    			flag = false;
	    		}
	    	}
	    	
	    	if(!flag){	//范围变更
	    		logger.debug("停用旧监测设置操作");
	    		o.setCheckState("0");//0：关闭监测设置
	    		//组织数据
	    		JSONObject jsonObj = new JSONObject();
	    		List<SetInfo> setInfoList = new ArrayList<SetInfo>();
	    		setInfoList.add(o);
	    		jsonObj.put("number", Calendar.getInstance().getTimeInMillis());
	    		jsonObj.put("setInfo", setInfoList);
	    		this.changeSetInfo(o,jsonObj, service);
	    	}else{	//范围无变化
	    	}
	    	SetInfo news = service.getSetInfoById(n.getId());
			//查询 变更的告警信息集合
			List<AlarmInfo> alarmInfoList = service.getAlarmInfoListBySetInfoId(news.getId());
	//----------------------------------------------------------------------
			//NMSServer 解析更新
			//checkType TableName Map Init
			service.updateCheckTableInfo(Common.getInsertTable(), news.getCheckTypeName());
			service.updateSetInfoName(Common.getSetInfoNameMape(), null);
			//tableMap Init
			service.updateTableColumnsMap(Common.getTableMap(), news.getCheckTypeName());
			//alarm Ping Init
			service.updateAlarmInfo(Common.getAlarmInfoMap(),news.getId());
	//----------------------------------------------------------------------
    		//5秒后执行新监测设置下发
			Thread.currentThread().sleep(5000);
			//组织数据
			logger.debug("下发新监测设置操作");
    		JSONObject jsonObj = new JSONObject();
    		List<SetInfo> setInfoList = new ArrayList<SetInfo>();
    		setInfoList.add(news);
    		jsonObj.put("number", Calendar.getInstance().getTimeInMillis());
    		jsonObj.put("setInfo", setInfoList);
    		jsonObj.put("alarmInfo", alarmInfoList);
    		this.changeSetInfo(news,jsonObj, service);
    		if(recordId!=null){
				service.deleteEventRecordByIds(recordId.toString());
			}
		} catch (Exception e) {
			logger.error("",e);
		}finally{
			if(dao!=null){
				dao.close();
				dao=null;
			}
		}
	}
	
	public void changeSetInfo(SetInfo info,JSONObject jObject,CommonService service){

		logger.info("监测设置"+info.getId()+" 指定CheckTypeName："+info.getCheckTypeName());
		logger.info("监测设置"+info.getId()+" 状态："+(StringUtils.isEmpty(info.getCheckState())?"无效操作":"1".equals(info.getCheckState())?"启动操作":"停用操作"));
		logger.info("监测设置"+info.getId()+" 节点组ID："+info.getNodeGroupsId());
		logger.info("监测设置"+info.getId()+" 指定Ip："+info.getNodeIpsId());
		//判断是主动监测还是被动监测
		if("0".equals(info.getCheckWay())){	//主动 server
			//监测重新载入
			new ThreadService().updateThread(info);
			
		}else {	//1被动  client
			
			//校验 变更范围的节点IP
			List<NodeModel> ipList = service.getNodeModelListBySetInfo(info);
			
			//工作数量对象(ipList.size()个工作数，阻塞当前线程执行，直至所有子线程完成执行)
//			CountDownLatch downLatch = new CountDownLatch(ipList.size());

			logger.debug("监测设置"+info.getId()+" 节点变更数量"+ipList.size());
			Iterator<NodeModel> ipIte = ipList.iterator();
			while (ipIte.hasNext()) {
				NodeModel ip = ipIte.next();
				 //仅向0服务器节点发送变更信息：0：服务器
				if(ip!= null && ip.getNodeIp()!= null && ip.getNodeType().longValue()==0l && Common.hasIpInIpSegment(ip.getNodeIp())){
		    		Common.runChangeRunnable(new ChangeSocketThread(null,ip.getNodeIp(),Constants.SSL_CLIENT_PORT,"char:updateConfig",jObject));
				}else{
//					downLatch.countDown();
				}
			}
		}
		
	}
	
    /**
     * Agent端通知变更方法
     * @time Sep 20, 2011-2:33:37 PM
     * @param ip
     * @param jObject
     */
    public void sendToClient(String ip,Object jObject) {
    	try {
    		Common.runChangeRunnable(new ChangeSocketThread(null,ip,Constants.SSL_CLIENT_PORT,"char:updateConfig",jObject));
		} catch (Exception e) {
			logger.debug("配置变更下发"+ip+"异常"+e.getMessage());
		}
	}
//	public static void main(String [] args) {
////		String[] datas = new String[]{"202","401"};
//		CommonDao dao = new CommonDao();
//		CommonService service = new CommonService(dao);
//		SetInfo old = service.getSetInfoById(226l);
//		SetInfo news = service.getSetInfoById(1l);
//		OperationsUpdateBySetInfo thread = new OperationsUpdateBySetInfo(old,news);
//		thread.run();
//		
//	}
}
