// ============================================================================
//
// = CONTEXT
//		Utility class - Implementation of a class encapsulating creation and control
//						of a Tango device proxy to a standard soleil motor
//
// = File
//		MotionProxyHelper.cpp
//
// = AUTHOR
//		Arafat NOUREDDINE - Synchrotron SOLEIL
//      F. Langlois - Synchrotron SOLEIL
//
// ============================================================================

#include <MotionProxyHelper.h>

namespace mph
{
//////////////////////////////////////////////////////////////////////////////////////
//-ctor
//////////////////////////////////////////////////////////////////////////////////////
	
MotionProxyHelper::MotionProxyHelper( 	const string sProxyName,
										const string sDescription,
										Tango::DeviceImpl * _device)
throw (Tango::DevFailed)
: Tango::LogAdapter((Tango::DeviceImpl *)_device)
{
	DEBUG_STREAM << "MotionProxyHelper::MotionProxyHelper() [ "<< sDescription<< " ] entering...  "  << endl;		
	//Init. members
	_sProxyName				= sProxyName;
	_sDescription			= sDescription;
	_sAttributePositionName	= "position";
	_sAttributeBLSWName		= "backwardLimitSwitch";
	_sAttributeFLSWName		= "forwardLimitSwitch";
	_sCommandStateName		= "State";
	_sCommandStatusName		= "Status";
	_sCommandStopName		= "Stop";
	_sCommandForwardName	= "Forward";
	_sCommandBackwardName	= "Backward";	
	_mProxy = 0;
	
	
	//fake motion proxy, nothing to do
	if(sProxyName == "none/none/none")
		return;
	
	//create proxy to the device
	try
	{
		_mProxy	=	new Tango::DeviceProxyHelper(sProxyName.c_str());
		if(_mProxy==0)
			throw std::bad_alloc();
		else
			_mProxy->get_device_proxy()->ping();				
	}
	catch (const std::bad_alloc&)
	{
		//ERROR_STREAM << "Bad alloc Exception" << ENDLOG;
		TangoSys_OMemStream o; 		
		o << "Unable to create proxy to " << _sDescription << " --> Memory allocation exception !" << endl;
		Tango::Except::throw_exception
			(
			static_cast<const char*>("OUT_OF_MEMORY"), 
			static_cast<const char*>(o.str().c_str()), 
			static_cast<const char*>("MotionProxyHelper::MotionProxyHelper()")
			); 		
	}	
	catch (Tango::DevFailed& e) 
	{		
		_mProxy = 0;
		//ERROR_STREAM << e << ENDLOG;
		TangoSys_OMemStream o; 		
		o << "Unable to create proxy to " << _sDescription << " --> check the Device proxy Name (" << _sProxyName << ") !" << endl;		
		Tango::Except::re_throw_exception 
			( e,
			  static_cast<const char*>("TANGO_DEVICE_ERROR"),
			  static_cast<const char*>(o.str().c_str()),
			  static_cast<const char*>("MotionProxyHelper::MotionProxyHelper()")
			);
	}
	catch(...)
	{
		_mProxy = 0;
		//ERROR_STREAM << "Unknown Exception" << ENDLOG;
		TangoSys_OMemStream o; 		
		o << "Unable to create proxy to " << _sDescription << " --> check the Device proxy Name (" << _sProxyName << ") !" << endl;
		Tango::Except::throw_exception
			(
			static_cast<const char*>("UNKNOWN_ERROR"), 
			static_cast<const char*>(o.str().c_str()), 
			static_cast<const char*>("MotionProxyHelper::MotionProxyHelper()")
			); 
	}	
}


//////////////////////////////////////////////////////////////////////////////////////
//-dtor
//////////////////////////////////////////////////////////////////////////////////////
MotionProxyHelper::~MotionProxyHelper() 
{
	DEBUG_STREAM << "MotionProxyHelper::~MotionProxyHelper() [ "<< _sDescription<< " ] entering...  "  << endl;		
	delete _mProxy;
}


//////////////////////////////////////////////////////////////////////////////////////
//- 
//////////////////////////////////////////////////////////////////////////////////////
void MotionProxyHelper::Move(double dMotorValue)
throw (Tango::DevFailed)
{
	DEBUG_STREAM << "MotionProxyHelper::Move() [ "<< _sDescription<< " ] entering...  "  << endl;	
	try
	{
		if(_mProxy!=0)
			_mProxy->write_attribute(_sAttributePositionName.c_str(),dMotorValue);
	}
	catch (Tango::DevFailed& e) 
	{		
		//ERROR_STREAM << e << ENDLOG;		
		TangoSys_OMemStream o; 		
		o << "Unable to write attribute "<<_sAttributePositionName <<" of the device " << _sDescription << " !" << endl;
		Tango::Except::re_throw_exception 
			( e,
			  static_cast<const char*>("TANGO_DEVICE_ERROR"),
			  static_cast<const char*>(o.str().c_str()),
			  static_cast<const char*>("MotionProxyHelper::Move()")
			);
	}
	catch(...)
	{
		//ERROR_STREAM << "Unknown Exception" << ENDLOG;
		TangoSys_OMemStream o; 		
		o << "Unable to write attribute "<<_sAttributePositionName <<" of the device " << _sDescription << " !" << endl;
		Tango::Except::throw_exception
			(
			static_cast<const char*>("UNKNOWN_ERROR"), 
			static_cast<const char*>(o.str().c_str()), 
			static_cast<const char*>("MotionProxyHelper::Move()")
			); 
	}		
}


//////////////////////////////////////////////////////////////////////////////////////
//- 
//////////////////////////////////////////////////////////////////////////////////////
void MotionProxyHelper::Stop(void)
throw (Tango::DevFailed)
{
	DEBUG_STREAM << "MotionProxyHelper::Stop() [ "<< _sDescription<< " ] entering...  "  << endl;	
	try
	{        
		if(_mProxy!=0)
			_mProxy->command(_sCommandStopName.c_str());
	}
	catch (Tango::DevFailed& e) 
	{		
		//ERROR_STREAM << e << ENDLOG;		
		TangoSys_OMemStream o; 		
		o << "Unable to execute command "<<_sCommandStopName <<" of the device " << _sDescription << " !" << endl;	
		Tango::Except::re_throw_exception 
			( e,
			  static_cast<const char*>("TANGO_DEVICE_ERROR"),
			  static_cast<const char*>(o.str().c_str()),
			  static_cast<const char*>("MotionProxyHelper::Stop()")
			);
	}
	catch(...)
	{
		//ERROR_STREAM << "Unknown Exception" << ENDLOG;
		TangoSys_OMemStream o; 		
		o << "Unable to execute command "<<_sCommandStopName <<" of the device " << _sDescription << " !" << endl;
		Tango::Except::throw_exception
			(
			static_cast<const char*>("UNKNOWN_ERROR"), 
			static_cast<const char*>(o.str().c_str()), 
			static_cast<const char*>("MotionProxyHelper::Stop()")
			); 
	}		
}

//////////////////////////////////////////////////////////////////////////////////////
//- 
//////////////////////////////////////////////////////////////////////////////////////
void MotionProxyHelper::Forward(void)
throw (Tango::DevFailed)
{
	DEBUG_STREAM << "MotionProxyHelper::Forward() [ "<< _sDescription<< " ] entering...  "  << endl;	
	try
	{        
		if(_mProxy!=0)
			_mProxy->command(_sCommandForwardName.c_str());
	}
	catch (Tango::DevFailed& e) 
	{		
		//ERROR_STREAM << e << ENDLOG;		
		TangoSys_OMemStream o; 		
		o << "Unable to execute command "<<_sCommandForwardName <<" of the device " << _sDescription << " !" << endl;	
		Tango::Except::re_throw_exception 
			( e,
			  static_cast<const char*>("TANGO_DEVICE_ERROR"),
			  static_cast<const char*>(o.str().c_str()),
			  static_cast<const char*>("MotionProxyHelper::Forward()")
			);
	}
	catch(...)
	{
		//ERROR_STREAM << "Unknown Exception" << ENDLOG;
		TangoSys_OMemStream o; 		
		o << "Unable to execute command "<<_sCommandForwardName <<" of the device " << _sDescription << " !" << endl;
		Tango::Except::throw_exception
			(
			static_cast<const char*>("UNKNOWN_ERROR"), 
			static_cast<const char*>(o.str().c_str()), 
			static_cast<const char*>("MotionProxyHelper::Forward()")
			); 
	}		
}

//////////////////////////////////////////////////////////////////////////////////////
//- 
//////////////////////////////////////////////////////////////////////////////////////
void MotionProxyHelper::Backward(void)
throw (Tango::DevFailed)
{
	DEBUG_STREAM << "MotionProxyHelper::Backward() [ "<< _sDescription<< " ] entering...  "  << endl;	
	try
	{        
		if(_mProxy!=0)
			_mProxy->command(_sCommandBackwardName.c_str());
	}
	catch (Tango::DevFailed& e) 
	{		
		//ERROR_STREAM << e << ENDLOG;		
		TangoSys_OMemStream o; 		
		o << "Unable to execute command "<<_sCommandBackwardName <<" of the device " << _sDescription << " !" << endl;	
		Tango::Except::re_throw_exception 
			( e,
			  static_cast<const char*>("TANGO_DEVICE_ERROR"),
			  static_cast<const char*>(o.str().c_str()),
			  static_cast<const char*>("MotionProxyHelper::Backward()")
			);
	}
	catch(...)
	{
		//ERROR_STREAM << "Unknown Exception" << ENDLOG;
		TangoSys_OMemStream o; 		
		o << "Unable to execute command "<<_sCommandBackwardName <<" of the device " << _sDescription << " !" << endl;
		Tango::Except::throw_exception
			(
			static_cast<const char*>("UNKNOWN_ERROR"), 
			static_cast<const char*>(o.str().c_str()), 
			static_cast<const char*>("MotionProxyHelper::Backward()")
			); 
	}		
}

//////////////////////////////////////////////////////////////////////////////////////
//- 
//////////////////////////////////////////////////////////////////////////////////////
double MotionProxyHelper::Read(void)
throw (Tango::DevFailed)
{
	DEBUG_STREAM << "MotionProxyHelper::Read() [ "<< _sDescription<< " ] entering...  "  << endl;	
	double dMotorValue=0.0;
	try
	{
		if(_mProxy!=0)
			_mProxy->read_attribute(_sAttributePositionName.c_str(),dMotorValue);
	}
	catch (Tango::DevFailed& e) 
	{		
		//ERROR_STREAM << e << ENDLOG;		
		TangoSys_OMemStream o; 		
		o << "Unable to read attribute "<<_sAttributePositionName <<" of the device " << _sDescription << " !" << endl;
		Tango::Except::re_throw_exception 
			( e,
			  static_cast<const char*>("TANGO_DEVICE_ERROR"),
			  static_cast<const char*>(o.str().c_str()),
			  static_cast<const char*>("MotionProxyHelper::Read()")
			);
	}
	catch(...)
	{
		//ERROR_STREAM << "Unknown Exception" << ENDLOG;
		TangoSys_OMemStream o; 		
		o << "Unable to read attribute "<<_sAttributePositionName <<" of the device " << _sDescription << " !" << endl;
		Tango::Except::throw_exception
			(
			static_cast<const char*>("UNKNOWN_ERROR"), 
			static_cast<const char*>(o.str().c_str()), 
			static_cast<const char*>("MotionProxyHelper::Read()")
			); 
	}
	return dMotorValue;
}

//////////////////////////////////////////////////////////////////////////////////////
//- 
//////////////////////////////////////////////////////////////////////////////////////
double MotionProxyHelper::ReadW(void)
throw (Tango::DevFailed)
{
	DEBUG_STREAM << "MotionProxyHelper::ReadW() [ "<< _sDescription<< " ] entering...  "  << endl;		
	double dMotorValue=0.0;
	try
	{
		if(_mProxy!=0)
			_mProxy->read_attribute_w(_sAttributePositionName.c_str(),dMotorValue);
	}
	catch (Tango::DevFailed& e) 
	{		
		//ERROR_STREAM << e << ENDLOG;		
		TangoSys_OMemStream o; 		
		o << "Unable to read attribute "<<_sAttributePositionName <<" of the device " << _sDescription << " !" << endl;
		Tango::Except::re_throw_exception 
			( e,
			  static_cast<const char*>("TANGO_DEVICE_ERROR"),
			  static_cast<const char*>(o.str().c_str()),
			  static_cast<const char*>("MotionProxyHelper::ReadW()")
			);
	}
	catch(...)
	{
		//ERROR_STREAM << "Unknown Exception" << ENDLOG;
		TangoSys_OMemStream o; 		
		o << "Unable to read attribute "<<_sAttributePositionName <<" of the device " << _sDescription << " !" << endl;
		Tango::Except::throw_exception
			(
			static_cast<const char*>("UNKNOWN_ERROR"), 
			static_cast<const char*>(o.str().c_str()), 
			static_cast<const char*>("MotionProxyHelper::ReadW()")
			); 
	}
	return dMotorValue;
}

//////////////////////////////////////////////////////////////////////////////////////
//- 
//////////////////////////////////////////////////////////////////////////////////////
bool MotionProxyHelper::ReadBLSW(void)
throw (Tango::DevFailed)
{
	DEBUG_STREAM << "MotionProxyHelper::ReadBLSW() [ "<< _sDescription<< " ] entering...  "  << endl;	
	bool bBLSWValue = false;
	try
	{
		if(_mProxy!=0)
			_mProxy->read_attribute(_sAttributeBLSWName.c_str(),bBLSWValue);
	}
	catch (Tango::DevFailed& e) 
	{		
		//ERROR_STREAM << e << ENDLOG;		
		TangoSys_OMemStream o; 		
		o << "Unable to read attribute "<<_sAttributeBLSWName <<" of the device " << _sDescription << " !" << endl;
		Tango::Except::re_throw_exception 
			( e,
			  static_cast<const char*>("TANGO_DEVICE_ERROR"),
			  static_cast<const char*>(o.str().c_str()),
			  static_cast<const char*>("MotionProxyHelper::ReadBLSW()")
			);
	}
	catch(...)
	{
		//ERROR_STREAM << "Unknown Exception" << ENDLOG;
		TangoSys_OMemStream o; 		
		o << "Unable to read attribute "<<_sAttributeBLSWName <<" of the device " << _sDescription << " !" << endl;
		Tango::Except::throw_exception
			(
			static_cast<const char*>("UNKNOWN_ERROR"), 
			static_cast<const char*>(o.str().c_str()), 
			static_cast<const char*>("MotionProxyHelper::ReadBLSW()")
			); 
	}
	return bBLSWValue;
}

//////////////////////////////////////////////////////////////////////////////////////
//- 
//////////////////////////////////////////////////////////////////////////////////////
bool MotionProxyHelper::ReadFLSW(void)
throw (Tango::DevFailed)
{
	DEBUG_STREAM << "MotionProxyHelper::ReadFLSW() [ "<< _sDescription<< " ] entering...  "  << endl;	
	bool bFLSWValue = false;
	try
	{
		if(_mProxy!=0)
			_mProxy->read_attribute(_sAttributeFLSWName.c_str(),bFLSWValue);
	}
	catch (Tango::DevFailed& e) 
	{
		//ERROR_STREAM << e << ENDLOG;		
		TangoSys_OMemStream o; 		
		o << "Unable to read attribute "<<_sAttributeFLSWName <<" of the device " << _sDescription << " !" << endl;
		Tango::Except::re_throw_exception 
			( e,
			  static_cast<const char*>("TANGO_DEVICE_ERROR"),
			  static_cast<const char*>(o.str().c_str()),
			  static_cast<const char*>("MotionProxyHelper::ReadFLSW()")
			);
	}
	catch(...)
	{
		//ERROR_STREAM << "Unknown Exception" << ENDLOG;
		TangoSys_OMemStream o; 		
		o << "Unable to read attribute "<<_sAttributeFLSWName <<" of the device " << _sDescription << " !" << endl;
		Tango::Except::throw_exception
			(
			static_cast<const char*>("UNKNOWN_ERROR"), 
			static_cast<const char*>(o.str().c_str()), 
			static_cast<const char*>("MotionProxyHelper::ReadFLSW()")
			); 
	}
	return bFLSWValue;
}

//////////////////////////////////////////////////////////////////////////////////////
//- 
//////////////////////////////////////////////////////////////////////////////////////
Tango::DevState MotionProxyHelper::State(void)
throw (Tango::DevFailed)
{
	DEBUG_STREAM << "MotionProxyHelper::State() [ "<< _sDescription<< " ] entering...  "  << endl;			
	Tango::DevState MotorState = Tango::STANDBY;
	
	try
	{
		if(_mProxy!=0)
			_mProxy->command_out(_sCommandStateName.c_str(),MotorState);
	}
	catch (Tango::DevFailed& e) 
	{		
		//ERROR_STREAM << e << ENDLOG;		
		TangoSys_OMemStream o; 		
		o << "Unable to execute command "<<_sCommandStateName <<" of the device " << _sDescription << " !" << endl;
		Tango::Except::re_throw_exception 
			( e,
			  static_cast<const char*>("TANGO_DEVICE_ERROR"),
			  static_cast<const char*>(o.str().c_str()),
			  static_cast<const char*>("MotionProxyHelper::State()")
			);
	}
	catch(...)
	{
		//ERROR_STREAM << "Unknown Exception" << ENDLOG;
		TangoSys_OMemStream o; 		
		o << "Unable to execute command "<<_sCommandStateName <<" of the device " << _sDescription << " !" << endl;
		Tango::Except::throw_exception
			(
			static_cast<const char*>("UNKNOWN_ERROR"), 
			static_cast<const char*>(o.str().c_str()), 
			static_cast<const char*>("MotionProxyHelper::State()")
			); 
	}
	return MotorState;
}


//////////////////////////////////////////////////////////////////////////////////////
//- 
//////////////////////////////////////////////////////////////////////////////////////
string MotionProxyHelper::Status(void)
throw (Tango::DevFailed)
{
	DEBUG_STREAM << "MotionProxyHelper::State() [ "<< _sDescription<< " ] entering...  "  << endl;			
	string MotorStatus = "STANDBY";
	
	try
	{
		if(_mProxy!=0)
			_mProxy->command_out(_sCommandStatusName.c_str(),MotorStatus);
	}
	catch (Tango::DevFailed& e) 
	{		
		//ERROR_STREAM << e << ENDLOG;		
		TangoSys_OMemStream o; 		
		o << "Unable to execute command "<<_sCommandStatusName <<" of the device " << _sDescription << " !" << endl;
		Tango::Except::re_throw_exception 
			( e,
			  static_cast<const char*>("TANGO_DEVICE_ERROR"),
			  static_cast<const char*>(o.str().c_str()),
			  static_cast<const char*>("MotionProxyHelper::Status()")
			);
	}
	catch(...)
	{
		//ERROR_STREAM << "Unknown Exception" << ENDLOG;
		TangoSys_OMemStream o; 		
		o << "Unable to execute command "<<_sCommandStatusName <<" of the device " << _sDescription << " !" << endl;
		Tango::Except::throw_exception
			(
			static_cast<const char*>("UNKNOWN_ERROR"), 
			static_cast<const char*>(o.str().c_str()), 
			static_cast<const char*>("MotionProxyHelper::Status()")
			); 
	}
	return MotorStatus;
}
//////////////////////////////////////////////////////////////////////////////////////
}