package com.yeejoin.amos.iec104.tcp.client.invoke;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;

import com.yeejoin.amos.connect.dao.entity.PointConfigVo;
import org.apache.log4j.Logger;

import com.yeejoin.amos.iec104.business.constants.IEC104Constant;
import com.yeejoin.amos.iec104.business.entity.mybatis.RecData;
import com.yeejoin.amos.iec104.business.param.AlarmParam;
import com.yeejoin.amos.iec104.business.service.intfc.IClientListenService;
import com.yeejoin.amos.iec104.business.service.intfc.IConfService;
import com.yeejoin.amos.iec104.business.service.intfc.IPointConfigService;
import com.yeejoin.amos.iec104.context.FireAutoIntfContext;
import org.springframework.stereotype.Service;

public class RecDataQueue {
	
	private static final BlockingQueue<RecData> blockingQueue = new LinkedBlockingQueue<RecData>();
	private static final BlockingQueue<RecData> soeBlockingQueue = new LinkedBlockingQueue<RecData>();
	ScheduledExecutorService service_apdu = null;
	ScheduledExecutorService service_soe = null;
	IClientListenService clientListenService;
	IConfService confService;
	IPointConfigService pointConfigService;
	private volatile static RecDataQueue instance = null;
	
	private RecDataQueue() {
		clientListenService = (IClientListenService) FireAutoIntfContext.getInstance().getBean(IClientListenService.class);
		confService = (IConfService) FireAutoIntfContext.getInstance().getBean(IConfService.class);
		pointConfigService = (IPointConfigService) FireAutoIntfContext.getInstance().getBean(IPointConfigService.class);
	}
	
    public static RecDataQueue getInstance(){
    	//先检查实例是否存在，如果不存在才进入下面的同步块
         if(instance == null){
        	 //同步块，线程安全的创建实例
             synchronized(RecDataQueue.class){
            	 //再次检查实例是否存在，如果不存在才真的创建实例
                 if(instance == null){
                     instance = new RecDataQueue();
                 }
             }
         }
         return instance;
    }
	
    /**
     * 启动apdu数据消费任务
     */
    public void start() {
    	service_apdu = Executors.newSingleThreadScheduledExecutor();
        // 第二个参数为首次执行的延时时间，第三个参数为定时执行的间隔时间
    	service_apdu.execute(task_runnable);
    	service_soe = Executors.newSingleThreadScheduledExecutor();
    	service_soe.execute(soe_runnable);
    }
    
	public void add(RecData recData) {
		blockingQueue.add(recData);
	}
	
	Runnable task_runnable = new Runnable() {
        public void run() {
            while(true) {
            	try {
					RecData data = blockingQueue.take();
					if (data.getSoe() == 1) {
						Logger.getLogger(this.getClass()).debug("----> soe is event pointCode is " + data.getPointCode() );
						soeBlockingQueue.add(data);
//						sendAlarm(data);
					} else {
						AlarmParam alarm = new AlarmParam();
				    	alarm.setInformationAddress(data.getInformationAddress()+"");
				    	alarm.setState(data.getValue());
				    	alarm.setServiceId(data.getServerId());
				    	alarm.setIsInvalid(data.getIsInvalid());
				    	alarm.setPointCode(data.getPointCode());
				    	alarm.setSoe(data.getSoe());
						GeneralDataQueue.getInstance().add(alarm);
					}
				} catch (Exception  e) {
					Logger.getLogger(this.getClass()).error(e.getMessage());
					e.printStackTrace();
				}
            }
        }
    };
    
    
    Runnable soe_runnable = new Runnable() {
        public void run() {
            while(true) {
            	try {
					RecData data = soeBlockingQueue.take();
					sendAlarm(data);
				} catch (Exception  e) {
					Logger.getLogger(this.getClass()).error(e.getMessage());
					e.printStackTrace();
				}
            }
        }
    };
    
    public void sendAlarm(RecData data) {
    	AlarmParam alarm = new AlarmParam();
    	alarm.setInformationAddress(data.getInformationAddress()+"");
    	alarm.setState(data.getValue());
    	alarm.setServiceId(data.getServerId());
    	alarm.setIsInvalid(data.getIsInvalid());
    	PointConfigVo vo = pointConfigService.findByServicesIdAndInfoAddress(data.getServerId(), data.getInformationAddress());
    	alarm.setPointCode(vo.getPointCode());
    	alarm.setSoe(data.getSoe());
    	try {
//    		ConfigVo vo = confService.getServerByTypeAndServiceId("IEC_SERVER", data.getServerId());
    		clientListenService.sendData(IEC104Constant.ALARM_MESSAGE, vo.getChannelNo(), alarm);
		} catch (Exception e) {
			e.printStackTrace();
		}
    } 
}
