package astri.tcs.TCSHardwareDeviceImpl;

import java.io.IOException;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.omg.CORBA.LongHolder;
import alma.ACS.ROboolean;
import alma.ACS.RObooleanHelper;
import alma.ACS.RObooleanPOATie;
import alma.ACS.ROdouble;
import alma.ACS.ROdoubleHelper;
import alma.ACS.ROdoublePOATie;
import alma.ACS.ROdoubleSeq;
import alma.ACS.ROdoubleSeqHelper;
import alma.ACS.ROdoubleSeqPOATie;
import alma.ACS.ROfloat;
import alma.ACS.ROfloatHelper;
import alma.ACS.ROfloatPOATie;
import alma.ACS.ROfloatSeq;
import alma.ACS.ROfloatSeqHelper;
import alma.ACS.ROfloatSeqPOATie;
import alma.ACS.ROlong;
import alma.ACS.ROlongHelper;
import alma.ACS.ROlongLong;
import alma.ACS.ROlongLongHelper;
import alma.ACS.ROlongLongPOATie;
import alma.ACS.ROlongPOATie;
import alma.ACS.ROlongSeq;
import alma.ACS.ROlongSeqHelper;
import alma.ACS.ROlongSeqPOATie;
import alma.ACS.ROstring;
import alma.ACS.ROstringHelper;
import alma.ACS.ROstringPOATie;
import alma.ACS.ROstringSeq;
import alma.ACS.ROstringSeqHelper;
import alma.ACS.ROstringSeqPOATie;
import alma.ACS.ROuLongLong;
import alma.ACS.ROuLongLongHelper;
import alma.ACS.ROuLongLongPOATie;
import alma.ACS.RWboolean;
import alma.ACS.RWbooleanHelper;
import alma.ACS.RWbooleanPOATie;
import alma.ACS.RWdouble;
import alma.ACS.RWdoubleHelper;
import alma.ACS.RWdoublePOATie;
import alma.ACS.RWdoubleSeq;
import alma.ACS.RWdoubleSeqHelper;
import alma.ACS.RWdoubleSeqPOATie;
import alma.ACS.RWfloat;
import alma.ACS.RWfloatHelper;
import alma.ACS.RWfloatPOATie;
import alma.ACS.RWfloatSeq;
import alma.ACS.RWfloatSeqHelper;
import alma.ACS.RWfloatSeqPOATie;
import alma.ACS.RWlong;
import alma.ACS.RWlongHelper;
import alma.ACS.RWlongLong;
import alma.ACS.RWlongLongHelper;
import alma.ACS.RWlongLongPOATie;
import alma.ACS.RWlongPOATie;
import alma.ACS.RWlongSeq;
import alma.ACS.RWlongSeqHelper;
import alma.ACS.RWlongSeqPOATie;
import alma.ACS.RWstring;
import alma.ACS.RWstringHelper;
import alma.ACS.RWstringPOATie;
import alma.ACS.RWuLongLong;
import alma.ACS.RWuLongLongHelper;
import alma.ACS.RWuLongLongPOATie;
import alma.ACS.impl.CharacteristicComponentImpl;
import alma.ACS.impl.RObooleanImpl;
import alma.ACS.impl.ROdoubleImpl;
import alma.ACS.impl.ROdoubleSeqImpl;
import alma.ACS.impl.ROfloatImpl;
import alma.ACS.impl.ROfloatSeqImpl;
import alma.ACS.impl.ROlongImpl;
import alma.ACS.impl.ROlongLongImpl;
import alma.ACS.impl.ROlongSeqImpl;
import alma.ACS.impl.ROstringImpl;
import alma.ACS.impl.ROstringSeqImpl;
import alma.ACS.impl.ROuLongLongImpl;
import alma.ACS.impl.RWbooleanImpl;
import alma.ACS.impl.RWdoubleImpl;
import alma.ACS.impl.RWdoubleSeqImpl;
import alma.ACS.impl.RWfloatImpl;
import alma.ACS.impl.RWfloatSeqImpl;
import alma.ACS.impl.RWlongImpl;
import alma.ACS.impl.RWlongLongImpl;
import alma.ACS.impl.RWlongSeqImpl;
import alma.ACS.impl.RWstringImpl;
import alma.ACS.impl.RWuLongLongImpl;
import alma.ACS.jbaci.DataAccess;
import alma.ACS.jbaci.PropertyInitializationFailed;
import alma.ACS.jbaci.DataAccess.OnChangeNotSupportedException;
import alma.ACS.jbaci.DataAccess.ValueChangeListener;
import alma.ACSErr.Completion;
import alma.ACSErr.CompletionHolder;
import alma.acs.exceptions.AcsJCompletion;
import alma.acs.exceptions.AcsJException;
import alma.acs.util.UTCUtility;
import alma.alarmsystem.source.ACSAlarmSystemInterface;
import alma.alarmsystem.source.ACSAlarmSystemInterfaceFactory;
import alma.alarmsystem.source.ACSFaultState;
import astri.cta.acs.opcua.da.UaDataSupport.extensions.UaDataSupportInt16;
//import astri.tcs.TCSHardwareDeviceImpl.PropErrorListener;
import cta.acs.opcua.da.UaClientPool;
import cta.acs.opcua.da.UaDataSupport;
import cta.acs.opcua.da.UaSubscriptionListener;
import cta.acs.opcua.da.extension.UaDataSupportShort2Int;
import cta.acs.opcua.da.extension.UaDataSupportUInt16;
import cta.acs.opcua.da.extension.UaDataSupportUInt32;

public class baciHelper {
	
	
	protected class bclass{
		
		private String name;
		private String type;
		private Object prop;
		public bclass(String name,String type, Object prop) {
			super();
			this.name=name;
			this.type = type;
			this.prop = prop;
		}
		public String getType() {
			return type;
		}
		public void setType(String type) {
			this.type = type;
		}
		public Object getProp() {
			return prop;
		}
		public void setProp(Object prop) {
			this.prop = prop;
		}
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		
	}
	private String device=null;
	private Logger m_logger;
	private CharacteristicComponentImpl m_comp;
	protected Map<String, UaDataSupport> dataAccess = new HashMap<String, UaDataSupport>();
    protected Map<String, bclass> nodes = new HashMap<String, bclass>();
    private boolean isConnected=false;
    private String opc_url=null;
   // private myValueListener myL=null; // = new myDoubleListener(); 
    private UaSubscriptionListener myNL; //= new myNotificationListener();
    private PropErrorListener myEL=null;
    protected ConnectionListener commL=null;
    boolean notify=false;
    
	public enum AlarmState{
		ALARM_HI,
		ALARM_LOW,
		IN_RANGE,
		UNDEF
	}
	
	public enum ConnectionStatus{
		ALIVE,
		ERROR,
		TIMEOUT,
		BUFFEROVERFLOW,
		MISSINGDATA, CREATED, LIFETIMETIMEOUT
	}
	
	public void addErrorListener(PropErrorListener el) {
		if (myEL==null) {
			this.myEL=el;
			notify=true;
		}
	}
	public void removeErrorListener() {
		this.myEL=null;
		notify=false;
	}
	
    public class myNotificationListener implements UaSubscriptionListener{

		@Override
		public void onAlive() {
			m_logger.info("Server OPC-UA alive");
			commL.notify(opc_url, ConnectionStatus.ALIVE);
		}

		@Override
		public void onBufferOverflow(long arg0) {
			m_logger.warning("onBufferOverflow(): " + arg0);
			commL.notify(opc_url, ConnectionStatus.BUFFEROVERFLOW);
		}

		@Override
		public void onError(Exception arg0) {
			m_logger.severe("Server OPC-UA onError(): " + arg0.getMessage());;
			commL.notify(opc_url, ConnectionStatus.ERROR);
		}

		@Override
		public void onMissingData(long arg0, long arg1) {
			m_logger.warning("onMissingData(): " + arg0 + ", " + arg1);	
			commL.notify(opc_url, ConnectionStatus.MISSINGDATA);
		}

		@Override
		public void onTimeout() {
			m_logger.warning("onTimeout()");
			commL.notify(opc_url, ConnectionStatus.TIMEOUT);
		}

		@Override
		public void onAfterCreate() {
			m_logger.info("onAfterCreate()");
			commL.notify(opc_url, ConnectionStatus.CREATED);
			
		}

		@Override
		public void onLifetimeTimeout() {
			m_logger.warning("onLifetimeTimeout()");
			commL.notify(opc_url, ConnectionStatus.LIFETIMETIMEOUT);
			
		}
    	
    }
	
	public class myValueListener implements ValueChangeListener{    
		@Override
		public void valueChanged(DataAccess<?> source, Object oldValue, Object newValue) {
			if (oldValue !=null && newValue!=null) {
				UaDataSupport ap=(UaDataSupport) source;
				bclass  prop= nodes.get(ap.getNodeIdRefsAsStr());
				checkAlarm(prop.getName(), prop.getProp(),newValue);
				Double nvalue = (Double) newValue;
				String t = UTCUtility.getUTCDate(System.currentTimeMillis());
				m_logger.info("Received <"+t+">:"+prop.getName()+":"+prop.getType()+":"+nvalue.toString());
			}		
			//m_logger.info("Value Changed");
		} 	
    }
	
	public baciHelper(CharacteristicComponentImpl comp, Logger log) {
		super();
		this.m_logger=log;
		this.m_comp=comp;
		this.device=m_comp.name();
		
	}
	public void setOPCUAurl(String url) {
		this.opc_url=url;
	}
	
	
	public void createConnection(String url) {
		if (this.opc_url==null) {
			this.opc_url=url;
		}
		if (!isConnected) {
			m_logger.info("Calling method: tcshwInitialize() ");
			try {
	    		UaClientPool.create(opc_url);
	    		UaClientPool.connect(opc_url);		
	    		isConnected=true;
	    	} catch (IOException e1) {
	    		m_logger.log(Level.SEVERE,e1.getMessage());
	    		if (notify) {
	    			commL.notify(opc_url, ConnectionStatus.ERROR);
	    		}
			}
	    	
		}
	}
	
	public void closeConnection() {
		removeErrorListener();
		
		if (isConnected) {
			
			for (Map.Entry<String, UaDataSupport> entry : dataAccess.entrySet()) {
			    try {
			        entry.getValue().close();
			        m_logger.log(Level.FINE, "closing:" ,entry.getKey());
			    }
			    catch (IOException e) {
			        m_logger.log(Level.SEVERE, "IOException: " , e);
			    }
			}
			UaClientPool.shutdown();
		    isConnected=false;
		}	
	}
	
	public boolean isConnected() {
		if (isConnected)
			return true;
		else
			return false;
	}

	public void checkAlarm(String name, Object prop, Object value) {
		
		if (prop instanceof ROdouble) {
			ROdouble tmp =(ROdouble)prop;
			Double val = (Double) value;
			if (val > tmp.alarm_high_on()) {
				send_hi_Alarm(name, true);
				if(notify) {
					myEL.onError(name,AlarmState.ALARM_HI);
				}
			}
			if (val < tmp.alarm_low_on()) {
				send_low_Alarm(name, true);
				if(notify) {
					myEL.onError(name,AlarmState.ALARM_LOW);
				}
			}
//			else {
//				m_logger.info( "The value of:"+name+":"+value.toString()+" is within the allowed range");
//			}
		}else if (prop instanceof ROlong) {
			ROlong tmp =(ROlong)prop;
			Integer val = (Integer) value;
			if (val > tmp.alarm_high_on()) {
				send_hi_Alarm(name, true);
				if(notify) {
					myEL.onError(name,AlarmState.ALARM_HI);
				}
			}
			if (val < tmp.alarm_low_on()) {
				send_low_Alarm(name, true);
				if(notify) {
					myEL.onError(name,AlarmState.ALARM_LOW);
				}
			}
//			else {
//				m_logger.info( "The value of:"+name+":"+value.toString()+" is within the allowed range");
//			}
		}
		else if (prop instanceof ROlongLong) {
			ROlongLong tmp =(ROlongLong)prop;
			Long val = (Long) value;
			if (val > tmp.alarm_high_on()) {
				send_hi_Alarm(name, true);
				if(notify) {
					myEL.onError(name,AlarmState.ALARM_HI);
				}
			}
			if (val < tmp.alarm_low_on()) {
				send_low_Alarm(name, true);
				if(notify) {
					myEL.onError(name,AlarmState.ALARM_LOW);
				}
			}
//			else {
//				m_logger.info( "The value of:"+name+":"+value.toString()+" is within the allowed range");
//			}
		}
		else if (prop instanceof ROfloat) {
			ROfloat tmp =(ROfloat)prop;
			Float val = (Float) value;
			if (val > tmp.alarm_high_on()) {
				send_hi_Alarm(name, true);
				if(notify) {
					myEL.onError(name,AlarmState.ALARM_HI);
				}
			}
			if (val < tmp.alarm_low_on()) {
				send_low_Alarm(name, true);
				if(notify) {
					myEL.onError(name,AlarmState.ALARM_LOW);
				}
			}
//			else {
//				m_logger.info( "The value of:"+name+":"+value.toString()+" is within the allowed range");
//			}
		}
		else {
			m_logger.info("UNSUPPORTED TYPE");
				
		}
	}
	
	public void addConnectionListener(ConnectionListener cl) {
		this.commL=cl;
	}
	
	public void addValueListener(String name, double samplingInt, double publInt) throws IOException, OnChangeNotSupportedException {
		dataAccess.get(name).setSamplingInterval(samplingInt);
		dataAccess.get(name).setPublishingInterval(publInt);
		dataAccess.get(name).addValueChangeListener(new myValueListener());
	}
	
	public ROdouble createROdoubleProp(String name, String Node) throws PropertyInitializationFailed, IOException, OnChangeNotSupportedException {
		dataAccess.put(name, new UaDataSupport(opc_url,Node));
		
		ROdoubleImpl impl = new ROdoubleImpl(name, m_comp, dataAccess.get(name));
		ROdouble prop= ROdoubleHelper.narrow(m_comp.registerProperty(impl, new ROdoublePOATie(impl)));
		nodes.put("["+Node+"]", new bclass(name,"ROdouble",prop));
		dataAccess.get(name).setNotificationListener(myNL);
		return prop;
	}
	public ROfloat createROfloatProp(String name, String Node) throws PropertyInitializationFailed, IOException, OnChangeNotSupportedException {
		dataAccess.put(name, new UaDataSupport(opc_url,Node));
		ROfloatImpl impl = new ROfloatImpl(name, m_comp, dataAccess.get(name));
		ROfloat prop =ROfloatHelper.narrow(m_comp.registerProperty(impl, new ROfloatPOATie(impl)));
		nodes.put("["+Node+"]", new bclass(name,"ROfloat",prop));
		dataAccess.get(name).setNotificationListener(myNL);
		//addValueListener(name);
		return prop;
	}
	public ROstring createROstringProp(String name, String Node) throws PropertyInitializationFailed, IOException, OnChangeNotSupportedException {
		dataAccess.put(name, new UaDataSupport(opc_url,Node));
		ROstringImpl impl = new ROstringImpl(name, m_comp, dataAccess.get(name));
		ROstring prop= ROstringHelper.narrow(m_comp.registerProperty(impl, new ROstringPOATie(impl)));
		nodes.put("["+Node+"]", new bclass(name,"ROstring",prop));
		dataAccess.get(name).setNotificationListener(myNL);
		//addValueListener(name);
		return prop;
	}
	public ROlong createROlongProp(String name, String Node) throws PropertyInitializationFailed, IOException, OnChangeNotSupportedException {
		dataAccess.put(name, new UaDataSupport(opc_url,Node));
		ROlongImpl impl = new ROlongImpl(name, m_comp, dataAccess.get(name));
		ROlong prop= ROlongHelper.narrow(m_comp.registerProperty(impl, new ROlongPOATie(impl)));
		nodes.put("["+Node+"]", new bclass(name,"ROlong",prop));
		dataAccess.get(name).setNotificationListener(myNL);
		//addValueListener(name);
		return prop;
	}
	public ROlong createROlongProp(String name, String Node, String flag) throws PropertyInitializationFailed, IOException, OnChangeNotSupportedException {
		if (flag=="INT16")
			//dataAccess.put(name, new UaDataSupportInt16(opc_url,Node));
			dataAccess.put(name, new UaDataSupportShort2Int(opc_url,Node));
		else if(flag=="UINT16")
			dataAccess.put(name, new UaDataSupportUInt16(opc_url,Node));
		else if(flag=="UINT32")
			dataAccess.put(name, new UaDataSupportUInt32(opc_url,Node));
		ROlongImpl impl = new ROlongImpl(name, m_comp, dataAccess.get(name));
		ROlong prop= ROlongHelper.narrow(m_comp.registerProperty(impl, new ROlongPOATie(impl)));
		nodes.put("["+Node+"]", new bclass(name,"ROlong",prop));
		dataAccess.get(name).setNotificationListener(myNL);
		//addValueListener(name);
		return prop;
	}
    public ROlongLong createROlongLongProp(String name, String Node) throws PropertyInitializationFailed, IOException, OnChangeNotSupportedException {
    	dataAccess.put(name, new UaDataSupport(opc_url,Node));
    	ROlongLongImpl impl = new ROlongLongImpl(name, m_comp, dataAccess.get(name));
        ROlongLong prop= ROlongLongHelper.narrow(m_comp.registerProperty(impl, new ROlongLongPOATie(impl)));
        nodes.put("["+Node+"]", new bclass(name,"ROlongLong",prop));
		dataAccess.get(name).setNotificationListener(myNL);
		//addValueListener(name);
		return prop;
    }
	public ROuLongLong createROuLongLongProp(String name, String Node) throws PropertyInitializationFailed, IOException, OnChangeNotSupportedException {
		dataAccess.put(name, new UaDataSupport(opc_url,Node));       
		ROuLongLongImpl impl = new ROuLongLongImpl(name, m_comp, dataAccess.get(name));
        ROuLongLong prop=ROuLongLongHelper.narrow(m_comp.registerProperty(impl, new ROuLongLongPOATie(impl)));
        nodes.put("["+Node+"]", new bclass(name,"ROlong",prop));
		dataAccess.get(name).setNotificationListener(myNL);
		//addValueListener(name);
		return prop;
        }
	public RWuLongLong createRWuLongLongProp(String name, String Node) throws PropertyInitializationFailed {
		dataAccess.put(name, new UaDataSupport(opc_url,Node));    
		RWuLongLongImpl impl = new RWuLongLongImpl(name, m_comp, dataAccess.get(name));
        return RWuLongLongHelper.narrow(m_comp.registerProperty(impl, new RWuLongLongPOATie(impl)));
        }
	public ROboolean createRObooleanProp(String name, String Node) throws PropertyInitializationFailed {
		dataAccess.put(name, new UaDataSupport(opc_url,Node));
		RObooleanImpl impl = new RObooleanImpl(name, m_comp, dataAccess.get(name));
		ROboolean prop=RObooleanHelper.narrow(m_comp.registerProperty(impl, new RObooleanPOATie(impl)));
		nodes.put("["+Node+"]", new bclass(name,"ROboolean",prop));
		dataAccess.get(name).setNotificationListener(myNL);
		return prop;
	}
	public RWdouble createRWdoubleProp(String name, String Node) throws PropertyInitializationFailed {
		dataAccess.put(name, new UaDataSupport(opc_url,Node));
		RWdoubleImpl impl = new RWdoubleImpl(name, m_comp, dataAccess.get(name));
		return RWdoubleHelper.narrow(m_comp.registerProperty(impl, new RWdoublePOATie(impl)));
	}
	public RWfloat createRWfloatProp(String name, String Node) throws PropertyInitializationFailed {
		dataAccess.put(name, new UaDataSupport(opc_url,Node));
		RWfloatImpl impl = new RWfloatImpl(name, m_comp, dataAccess.get(name));
		return RWfloatHelper.narrow(m_comp.registerProperty(impl, new RWfloatPOATie(impl)));
	}
	public RWstring createRWstringProp(String name, String Node) throws PropertyInitializationFailed {
		dataAccess.put(name, new UaDataSupport(opc_url,Node));
		RWstringImpl impl = new RWstringImpl(name, m_comp, dataAccess.get(name));
		return RWstringHelper.narrow(m_comp.registerProperty(impl, new RWstringPOATie(impl)));
	}
	public RWlong createRWlongProp(String name, String Node) throws PropertyInitializationFailed {
		dataAccess.put(name, new UaDataSupport(opc_url,Node));
		RWlongImpl impl = new RWlongImpl(name, m_comp, dataAccess.get(name));
		return RWlongHelper.narrow(m_comp.registerProperty(impl, new RWlongPOATie(impl)));
	}
	public RWlong createRWlongProp(String name, String Node, String flag) throws PropertyInitializationFailed {
		if (flag=="INT16")
			//dataAccess.put(name, new UaDataSupportInt16(opc_url,Node));
			dataAccess.put(name, new UaDataSupportShort2Int(opc_url,Node));
		else if(flag=="UINT16")
			dataAccess.put(name, new UaDataSupportUInt16(opc_url,Node));
		else if(flag=="UINT32")
			dataAccess.put(name, new UaDataSupportUInt32(opc_url,Node));

		RWlongImpl impl = new RWlongImpl(name, m_comp, dataAccess.get(name));
		return RWlongHelper.narrow(m_comp.registerProperty(impl, new RWlongPOATie(impl)));
	}
    public RWlongLong createRWlongLongProp(String name, String Node) throws PropertyInitializationFailed {
    	dataAccess.put(name, new UaDataSupport(opc_url,Node));
    	RWlongLongImpl impl = new RWlongLongImpl(name, m_comp, dataAccess.get(name));
        return RWlongLongHelper.narrow(m_comp.registerProperty(impl, new RWlongLongPOATie(impl)));
        }
	public RWboolean createRWbooleanProp(String name, String Node) throws PropertyInitializationFailed {
		UaDataSupport uas= new UaDataSupport(opc_url,Node);
		uas.setConversionToPrimitiveArrayEnabled(true);
		dataAccess.put(name, uas);
		RWbooleanImpl impl = new RWbooleanImpl(name, m_comp, dataAccess.get(name));
		return RWbooleanHelper.narrow(m_comp.registerProperty(impl, new RWbooleanPOATie(impl)));
	}
	public ROlongSeq createROlongSeqProp(String name, String Node) throws PropertyInitializationFailed {
		UaDataSupport uas= new UaDataSupport(opc_url,Node);
		uas.setConversionToPrimitiveArrayEnabled(true);
		dataAccess.put(name, uas);
		ROlongSeqImpl impl = new ROlongSeqImpl(name, m_comp, dataAccess.get(name));
		return ROlongSeqHelper.narrow(m_comp.registerProperty(impl, new ROlongSeqPOATie(impl)));
	}
	public RWlongSeq createRWlongSeqProp(String name, String Node) throws PropertyInitializationFailed {
		UaDataSupport uas= new UaDataSupport(opc_url,Node);
		uas.setConversionToPrimitiveArrayEnabled(true);
		dataAccess.put(name, uas);
		RWlongSeqImpl impl = new RWlongSeqImpl(name, m_comp, dataAccess.get(name));
		return RWlongSeqHelper.narrow(m_comp.registerProperty(impl, new RWlongSeqPOATie(impl)));
	}
	public ROfloatSeq createROfloatSeqProp(String name, String Node) throws PropertyInitializationFailed {
		UaDataSupport uas= new UaDataSupport(opc_url,Node);
		uas.setConversionToPrimitiveArrayEnabled(true);
		dataAccess.put(name, uas);
		ROfloatSeqImpl impl = new ROfloatSeqImpl(name, m_comp, dataAccess.get(name));
		return ROfloatSeqHelper.narrow(m_comp.registerProperty(impl, new ROfloatSeqPOATie(impl)));
	}
	public RWfloatSeq createRWfloatSeqProp(String name, String Node) throws PropertyInitializationFailed {
		UaDataSupport uas= new UaDataSupport(opc_url,Node);
		uas.setConversionToPrimitiveArrayEnabled(true);
		dataAccess.put(name, uas);
		RWfloatSeqImpl impl = new RWfloatSeqImpl(name, m_comp, dataAccess.get(name));
		return RWfloatSeqHelper.narrow(m_comp.registerProperty(impl, new RWfloatSeqPOATie(impl)));
	}
	public ROdoubleSeq createROdoubleSeqProp(String name, String Node) throws PropertyInitializationFailed {
		UaDataSupport uas= new UaDataSupport(opc_url,Node);
		uas.setConversionToPrimitiveArrayEnabled(true);
		dataAccess.put(name, uas);
		ROdoubleSeqImpl impl = new ROdoubleSeqImpl(name, m_comp, dataAccess.get(name));
		return ROdoubleSeqHelper.narrow(m_comp.registerProperty(impl, new ROdoubleSeqPOATie(impl)));
	}
	public RWdoubleSeq createRWdoubleSeqProp(String name, String Node) throws PropertyInitializationFailed {
		UaDataSupport uas= new UaDataSupport(opc_url,Node);
		uas.setConversionToPrimitiveArrayEnabled(true);
		dataAccess.put(name, uas);
		RWdoubleSeqImpl impl = new RWdoubleSeqImpl(name, m_comp, dataAccess.get(name));
		return RWdoubleSeqHelper.narrow(m_comp.registerProperty(impl, new RWdoubleSeqPOATie(impl)));
	}
	public ROstringSeq createROstringSeqProp(String name, String Node) throws PropertyInitializationFailed {
		UaDataSupport uas= new UaDataSupport(opc_url,Node);
		uas.setConversionToPrimitiveArrayEnabled(true);
		dataAccess.put(name, uas);
		ROstringSeqImpl impl = new ROstringSeqImpl(name, m_comp, dataAccess.get(name));
		return ROstringSeqHelper.narrow(m_comp.registerProperty(impl, new ROstringSeqPOATie(impl)));
	}
	
	private boolean checkCompletion(CompletionHolder c, String name,LongHolder arg0) {
		if (c.value != null) {
			AcsJCompletion compl = AcsJCompletion.fromCorbaCompletion(c.value);
			if (compl.isError()) {
				m_logger.log(Level.SEVERE,"failed read property!", compl.getAcsJException());
				return false;
			}else{
				arg0.value=c.value.timeStamp;
				return true;
			}
		}else{
			//m_logger.info("read property "+ name+" at t="+ UTCUtility.getUTCDate(arg0.value/10000));
			return false;
		}
	}
	

	
	public double getDoubleValSync(Object prop, LongHolder arg0) {
		CompletionHolder c = new CompletionHolder();
		double val = Double.NaN;	
		String name=null;
		if (prop!=null){
			if (prop instanceof ROdouble) {
			    ROdouble prop1 = (ROdouble) prop;
			    val=prop1.get_sync(c);
			    name = prop1.name();
			}
			if (prop instanceof RWdouble) {
				RWdouble prop1=(RWdouble)prop;
				val=prop1.get_sync(c);
			    name = prop1.name();
			}
			if (checkCompletion(c, name,arg0)) {
				m_logger.info("read property "+ name+":"+val+" at t="+ UTCUtility.getUTCDate(UTCUtility.utcOmgToJava(arg0.value)));
			}else {
				return val;
			}
				
		}else{
			m_logger.log(Level.SEVERE,"property is not initialized");
		}
		return val;
	}

	public double[] getDoubleArrayValSync(Object prop, LongHolder arg0) {
		CompletionHolder c = new CompletionHolder();
		double[] val = null;	
		String name=null;
		if (prop!=null){
			if (prop instanceof ROdoubleSeq) {
			    ROdoubleSeq prop1 = (ROdoubleSeq) prop;
			    val=prop1.get_sync(c);
			    name = prop1.name();
			}
			if (prop instanceof RWdoubleSeq) {
				RWdoubleSeq prop1=(RWdoubleSeq)prop;
				val=prop1.get_sync(c);
			    name = prop1.name();
			}
			if (checkCompletion(c, name,arg0)) {
				m_logger.info("read property "+ name+":"+val.toString()+" at t="+ UTCUtility.getUTCDate(UTCUtility.utcOmgToJava(arg0.value)));
			}else {
				return val;
			}
				
		}else{
			m_logger.log(Level.SEVERE,"property is not initialized");
		}
		return val;
	}	
	
	
	
	public int[] getIntArrayValSync(Object prop, LongHolder arg0) {
		CompletionHolder c = new CompletionHolder();
		int[] val = null;
		String name=null;
		if (prop!=null){
			if (prop instanceof ROlongSeq) {
			    ROlongSeq prop1 = (ROlongSeq) prop;
			    val=prop1.get_sync(c);
			    name = prop1.name();
			}
			if (prop instanceof RWlongSeq) {
				RWlongSeq prop1=(RWlongSeq)prop;
				val=prop1.get_sync(c);
			    name = prop1.name();
			}
			if (checkCompletion(c, name,arg0)) {
				m_logger.info("read property "+ name+":"+val.toString()+" at t="+ UTCUtility.getUTCDate(UTCUtility.utcOmgToJava(arg0.value)));
				return val;
			}else {
				return val;
			}
		}else{
			m_logger.log(Level.SEVERE,"property is not initialized");
		}
		return val;
	}
	
	public int getIntValSync(Object prop, LongHolder arg0) {
		CompletionHolder c = new CompletionHolder();
		int val = 0;
		String name=null;
		if (prop!=null){
			if (prop instanceof ROlong) {
			    ROlong prop1 = (ROlong) prop;
			    val=prop1.get_sync(c);
			    name = prop1.name();
			}
			if (prop instanceof RWlong) {
				RWlong prop1=(RWlong)prop;
				val=prop1.get_sync(c);
			    name = prop1.name();
			}
			if (checkCompletion(c, name,arg0)) {
				m_logger.info("read property "+ name+":"+val+" at t="+ UTCUtility.getUTCDate(UTCUtility.utcOmgToJava(arg0.value)));
				return val;
			}else {
				return val;
			}
		}else{
			m_logger.log(Level.SEVERE,"property is not initialized");
		}
		return val;
	}

	public long getLongValSync(Object prop, LongHolder arg0) {
		CompletionHolder c = new CompletionHolder();
		long val = Long.MAX_VALUE;;	
		String name=null;
		if (prop!=null){
			if (prop instanceof ROlongLong) {
			    ROlongLong prop1 = (ROlongLong) prop;
			    val=prop1.get_sync(c);
			    name = prop1.name();
			}
			if (prop instanceof RWlongLong) {
				RWlongLong prop1=(RWlongLong)prop;
				val=prop1.get_sync(c);
			    name = prop1.name();
			}
			if (checkCompletion(c, name,arg0)) {
				m_logger.info("read property "+ name+":"+val+" at t="+ UTCUtility.getUTCDate(UTCUtility.utcOmgToJava(arg0.value)));
			}else {
				return Long.MAX_VALUE;
			}
		}else{
			m_logger.log(Level.SEVERE,"property is not initialized");
		}
		return val;
	}

	
	public String getStringValSync(Object prop, LongHolder arg0) {
		CompletionHolder c = new CompletionHolder();
		String val = null;	
		String name=null;
		if (prop!=null){
			if (prop instanceof ROstring) {
			    ROstring prop1 = (ROstring) prop;
			    val=prop1.get_sync(c);
			    name = prop1.name();
			}
			if (prop instanceof RWstring) {
				RWstring prop1=(RWstring)prop;
				val=prop1.get_sync(c);
			    name = prop1.name();
			}
			if (checkCompletion(c, name,arg0)) {
				m_logger.info("read property "+ name+":"+val+" at t="+ UTCUtility.getUTCDate(UTCUtility.utcOmgToJava(arg0.value)));
			}else {
				return null;
			}
		}else{
			m_logger.log(Level.SEVERE,"property is not initialized");
		}
		return val;
	}

	public boolean getBooleanValSync(Object prop, LongHolder arg0) {
		CompletionHolder c = new CompletionHolder();
		boolean val = false;	
		String name=null;
		if (prop!=null){
			if (prop instanceof ROboolean) {
			    ROboolean prop1 = (ROboolean) prop;
			    val=prop1.get_sync(c);
			    name = prop1.name();
			}
			if (prop instanceof RWboolean) {
				RWboolean prop1=(RWboolean)prop;
				val=prop1.get_sync(c);
			    name = prop1.name();
			}
			if (checkCompletion(c, name,arg0)) {
				m_logger.info("read property "+ name+":"+val +" at t="+ UTCUtility.getUTCDate(UTCUtility.utcOmgToJava(arg0.value)));
			}else {
				return val;
			}
		}else{
			m_logger.log(Level.SEVERE,"property is not initialized");
		}
		return val;
	}
	
	public String[] getStringArrayValSync(Object prop, LongHolder arg0) {
		CompletionHolder c = new CompletionHolder();
		String[] val = null;	
		String name=null;
		if (prop!=null){
			if (prop instanceof ROstringSeq) {
			    ROstringSeq prop1 = (ROstringSeq) prop;
			    val=prop1.get_sync(c);
			    name = prop1.name();
			}
			if (checkCompletion(c, name,arg0)) {
				m_logger.info("read property "+ name+":"+val.toString()+" at t="+ UTCUtility.getUTCDate(UTCUtility.utcOmgToJava(arg0.value)));
			}else {
				return null;
			}
		}else{
			m_logger.log(Level.SEVERE,"property is not initialized");
		}
		return val;
	}
	
	public void setDoubleValSync(RWdouble prop, double arg0) {
		Completion c = new Completion();
		if (prop!=null){
			c=prop.set_sync(arg0);
			if(c!=null){
				AcsJCompletion compl = AcsJCompletion.fromCorbaCompletion(c);
				if (compl.isError()) {
					m_logger.log(Level.SEVERE, "failed set property!", compl.getAcsJException());
					try {
						throw compl.getAcsJException();
					} catch (AcsJException e) {
						m_logger.log(Level.SEVERE,e.getMessage());
					}
				}else{
					m_logger.info("set "+ prop.name()+" property to '" + arg0 + "'.");
				}
			}else{
				m_logger.info("set " +prop.name()+" property to '" + arg0 + "'.");
			}
		}
	}
	
	public void setDoubleArrayValSync(RWdoubleSeq prop, double[] arg0) {
		Completion c = new Completion();
		if (prop!=null){
			c=prop.set_sync(arg0);
			if(c!=null){
				AcsJCompletion compl = AcsJCompletion.fromCorbaCompletion(c);
				if (compl.isError()) {
					m_logger.log(Level.SEVERE, "failed set property!", compl.getAcsJException());
					try {
						throw compl.getAcsJException();
					} catch (AcsJException e) {
						m_logger.log(Level.SEVERE,e.getMessage());
					}
				}else{
					m_logger.info("set "+ prop.name()+" property to '" + arg0 + "'.");
				}
			}else{
				m_logger.info("set " +prop.name()+" property to '" + arg0 + "'.");
			}
		}
	}
	
	public void setIntValSync(RWlong prop, int arg0) {
		Completion c = new Completion();
		if (prop!=null){
			c=prop.set_sync(arg0);
			if(c!=null){
				AcsJCompletion compl = AcsJCompletion.fromCorbaCompletion(c);
				if (compl.isError()) {
					m_logger.log(Level.SEVERE, "failed set property!", compl.getAcsJException());
					try {
						throw compl.getAcsJException();
					} catch (AcsJException e) {
						m_logger.log(Level.SEVERE,e.getMessage());
					}
				}else{
					m_logger.info("set "+ prop.name()+" property to '" + arg0 + "'.");
				}
			}else{
				m_logger.info("set " +prop.name()+" property to '" + arg0 + "'.");
			}
		}
	}
	
	public void setIntArrayValSync(RWlongSeq prop, int[] arg0) {
		Completion c = new Completion();
		if (prop!=null){
			c=prop.set_sync(arg0);
			if(c!=null){
				AcsJCompletion compl = AcsJCompletion.fromCorbaCompletion(c);
				if (compl.isError()) {
					m_logger.log(Level.SEVERE, "failed set property!", compl.getAcsJException());
					try {
						throw compl.getAcsJException();
					} catch (AcsJException e) {
						m_logger.log(Level.SEVERE,e.getMessage());
					}
				}else{
					m_logger.info("set "+ prop.name()+" property to '" + arg0 + "'.");
				}
			}else{
				m_logger.info("set " +prop.name()+" property to '" + arg0 + "'.");
			}
		}
	}

	public void setLongValSync(RWlongLong prop, long arg0) {
	Completion c = new Completion();
	if (prop!=null){
		c=prop.set_sync(arg0);
		if(c!=null){
			AcsJCompletion compl = AcsJCompletion.fromCorbaCompletion(c);
			if (compl.isError()) {
				m_logger.log(Level.SEVERE, "failed set property!", compl.getAcsJException());
				try {
					throw compl.getAcsJException();
				} catch (AcsJException e) {
					m_logger.log(Level.SEVERE,e.getMessage());
				}
			}else{
				m_logger.info("set "+ prop.name()+" property to '" + arg0 + "'.");
			}
		}else{
			m_logger.info("set " +prop.name()+" property to '" + arg0 + "'.");
		}
	    }
	}
	
	public void setStringValSync(RWstring prop, String arg0) {
		Completion c = new Completion();
		if (prop!=null){
			c=prop.set_sync(arg0);
			if(c!=null){
				AcsJCompletion compl = AcsJCompletion.fromCorbaCompletion(c);
				if (compl.isError()) {
					m_logger.log(Level.SEVERE, "failed set property!", compl.getAcsJException());
					try {
						throw compl.getAcsJException();
					} catch (AcsJException e) {
						m_logger.log(Level.SEVERE,e.getMessage());
					}
				}else{
					m_logger.info("set "+ prop.name()+" property to '" + arg0 + "'.");
				}
			}else{
				m_logger.info("set " +prop.name()+" property to '" + arg0 + "'.");
			}
		}
	}

	
	public void setBooleanValSync(RWboolean prop, Boolean arg0) {
		Completion c = new Completion();
		if (prop!=null){
			c=prop.set_sync(arg0);
			if(c!=null){
				AcsJCompletion compl = AcsJCompletion.fromCorbaCompletion(c);
				if (compl.isError()) {
					m_logger.log(Level.SEVERE, "failed set property!", compl.getAcsJException());
					try {
						throw compl.getAcsJException();
					} catch (AcsJException e) {
						m_logger.log(Level.SEVERE,e.getMessage());
					}
				}else{
					m_logger.info("set "+ prop.name()+" property to '" + arg0.toString() + "'.");
				}
			}else{
				m_logger.info("set " +prop.name()+" property to '" + arg0.toString() + "'.");
			}
		}
	}
	
	public void send_hi_Alarm(String propName, boolean active) {
		String faultFamily = device+"_Prop_Alarms";
		int faultCode =1;
		String faultState;
		if (active) {
			faultState = ACSFaultState.ACTIVE;
		} else {
			faultState=ACSFaultState.TERMINATE;
		}
		send_alarm(faultFamily, propName, faultCode, faultState);
	}
	
	public void send_low_Alarm(String propName, boolean active) {
		String faultFamily = device+"_Prop_Alarms";
		int faultCode =2;
		String faultState;
		if (active) {
			faultState = ACSFaultState.ACTIVE;
		} else {
			faultState=ACSFaultState.TERMINATE;
		}
		send_alarm(faultFamily, propName, faultCode, faultState);
	}
	
	protected void send_alarm(String faultFamily, String faultMember,
			int faultCode, String faultState) {
		try {
			ACSAlarmSystemInterface alarmSource = ACSAlarmSystemInterfaceFactory
					.createSource("BACI");
			ACSFaultState fs = ACSAlarmSystemInterfaceFactory.createFaultState(
					faultFamily, faultMember, faultCode);
			fs.setDescriptor(faultState);
			fs.setUserTimestamp(new Timestamp(System.currentTimeMillis()));

	
			alarmSource.push(fs);

		} catch (Exception e) {
			m_logger.warning("Failure when sending alarm: " + e.getMessage());
		}
	}
}

