/*******************************************************************************
*    ALMA - Atacama Large Millimiter Array
*    (c) Associated Universities Inc., 2002 *
*    (c) European Southern Observatory, 2002
*    Copyright by ESO (in the framework of the ALMA collaboration)
*    and Cosylab 2002, All rights reserved
*
*    This library is free software; you can redistribute it and/or
*    modify it under the terms of the GNU Lesser General Public
*    License as published by the Free Software Foundation; either
*    version 2.1 of the License, or (at your option) any later version.
*
*    This library is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*    Lesser General Public License for more details.
*
*    You should have received a copy of the GNU Lesser General Public
*    License along with this library; if not, write to the Free Software
*    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA 
*
*
* "@(#) $Id: acsVltMountImpl.cpp,v 1.1 2004/01/28 11:38:34 bjeram Exp $"
*
*/

/*
 * This file contains the implementation of the special DevIO needed to
 * read VLT database attributes. Only the read method is implemented.
 *
 * Note that you need a synchronization guard before calling CCS db read function. 
 */
 
#include <acsVltMountImpl.h>

#include "ccs.h"
#include "err.h"
#include "msg.h"
#include "db.h"

/* ----------------------------------------------------------------*/
MountImpl::MountImpl(PortableServer::POA_ptr poa, const ACE_CString &_name) :
    CharacteristicComponentImpl(poa, _name),
    m_cmdAz_p(0),
    m_cmdEl_p(0),
    m_actAz_p(0),
    m_actEl_p(0)
{
    // This would talk to the "real" VLT Control Model in Garching
    //DevIODBRead* myDevIOAz  = new DevIODBRead("@wt0tcs:Appl_data:TCS:tif:data.azRef");
    //DevIODBRead* myDevIOAlt = new DevIODBRead("@wt0tcs:Appl_data:TCS:tif:data.altRef");

    // This talks to the local VLT Real Time Database
    DevIODBRead* myDevIOAz  = new DevIODBRead(":Appl_data:TCS:tif:data.azRef");
    DevIODBRead* myDevIOAlt = new DevIODBRead(":Appl_data:TCS:tif:data.altRef");

    // ACS_TRACE is used for debugging purposes
    ACS_TRACE("::MountImpl::MountImpl");

    // properties
    // the property's name must be composed of the server's name and the
    //   property name.
    m_cmdAz_p = new RWdouble(_name+":cmdAz", getComponent());
    // if this property wasn't created properly, we destroy it and all 
    //   of this component's previous properties
    CHARACTERISTIC_COMPONENT_PROPERTY(cmdAz, m_cmdAz_p);
	
    m_cmdEl_p = new RWdouble(_name+":cmdEl", getComponent());	
    CHARACTERISTIC_COMPONENT_PROPERTY(cmdEl, m_cmdEl_p);

    m_actAzSpeed_p = new ROdouble(_name+":actAzSpeed", getComponent());
    CHARACTERISTIC_COMPONENT_PROPERTY(actAzSpeed, m_actAzSpeed_p);

    m_actAz_p = new ROdouble(_name+":actAz", getComponent(), myDevIOAz);
    CHARACTERISTIC_COMPONENT_PROPERTY(actAz, m_actAz_p);


    m_actEl_p = new ROdouble(_name+":actEl", getComponent(), myDevIOAlt);	
    CHARACTERISTIC_COMPONENT_PROPERTY(actEl, m_actEl_p);

}

/* ----------------------------------------------------------------*/
MountImpl::~MountImpl()
{
    // ACS_TRACE is used for debugging purposes
    ACS_TRACE("::MountImpl::~MountImpl");
    ACS_DEBUG_PARAM("::MountImpl::~MountImpl", "Destroying %s...", name());

    // stop threads
    if (getComponent() != 0)
	{
	getComponent()->stopAllThreads();
	}
    
    // properties
    if (m_cmdAz_p != 0) 
	{ 
	m_cmdAz_p->destroy(); 
	m_cmdAz_p = 0; 
	}
    if (m_cmdEl_p != 0) 
	{ 
	m_cmdEl_p->destroy(); 
	m_cmdEl_p = 0; 
	}
    if (m_actAzSpeed_p != 0) 
	{ 
	m_actAzSpeed_p->destroy(); 
	m_actAzSpeed_p = 0; 
	}
    if (m_actAz_p != 0) 
	{ 
	m_actAz_p->destroy(); 
	m_actAz_p = 0; 
	}
    if (m_actEl_p != 0) 
	{ 
	m_actEl_p->destroy(); 
	m_actEl_p = 0; 
	}

}
/* --------------------- [ CORBA interface ] ----------------------*/
void 
MountImpl::objfix (CORBA::Double az,
		    CORBA::Double elev)
    throw (CORBA::SystemException)
{
    int errcode;
    unsigned long long timestamp;
    
    m_cmdAz_p->getDevIO()->write(az, errcode, timestamp);
    m_cmdEl_p->getDevIO()->write(elev, errcode, timestamp);
    
    cout << "Received objfix command. Az: " << az << " El: " << elev << endl; 
}

ACS::RWdouble_ptr
MountImpl::cmdAz ()
    throw (CORBA::SystemException)
{
    if (m_cmdAz_p == 0)
	{
	return ACS::RWdouble::_nil();
	}

    ACS::RWdouble_var prop = ACS::RWdouble::_narrow(m_cmdAz_p->getCORBAReference());
    return prop._retn();
}


ACS::RWdouble_ptr
MountImpl::cmdEl ()
    throw (CORBA::SystemException)
{
    if (m_cmdEl_p == 0)
	{
	return ACS::RWdouble::_nil();
	}

    ACS::RWdouble_var prop = ACS::RWdouble::_narrow(m_cmdEl_p->getCORBAReference());
    return prop._retn();
}


ACS::ROdouble_ptr
MountImpl::actAzSpeed ()
    throw (CORBA::SystemException)
{
    if (m_actAzSpeed_p == 0)
	{
	return ACS::ROdouble::_nil();
	}

    ACS::ROdouble_var prop = ACS::ROdouble::_narrow(m_actAzSpeed_p->getCORBAReference());
    return prop._retn();
}


ACS::ROdouble_ptr
MountImpl::actAz ()
    throw (CORBA::SystemException)
{
    if (m_actAz_p == 0)
	{
	return ACS::ROdouble::_nil();
	}

    ACS::ROdouble_var prop = ACS::ROdouble::_narrow(m_actAz_p->getCORBAReference());
    return prop._retn();
}


ACS::ROdouble_ptr
MountImpl::actEl ()
    throw (CORBA::SystemException)
{
    if (m_actEl_p == 0)
	{
	return ACS::ROdouble::_nil();
	}
    
    ACS::ROdouble_var prop = ACS::ROdouble::_narrow(m_actEl_p->getCORBAReference());
    return prop._retn();
}


BACIMutex DevIODBRead::m_dbAccessMutex;

DevIODBRead::DevIODBRead(char* dbAddr)
    : m_value(0.0)
{
    strcpy(m_dbAddr,dbAddr);
}

double
DevIODBRead::read(int& errcode, unsigned long long& timestamp)
{
    ccsCOMPL_STAT    locstat;

    dbTYPE                dataType;
    vltINT32              actual;
    vltUINT16             recordCnt;
    dbATTRTYPE            attrType;
    ccsERROR              error;

    // ccsInit("DevIODBRead");

    cout << "Reading:" << m_dbAddr << "\n";

    {
    ThreadSyncGuard guard(&m_dbAccessMutex);
    locstat = dbReadSymbolic(m_dbAddr,"",
			     &dataType,
			     (char*) &m_value,
			     sizeof(double),
			     &actual,
			     &recordCnt,
			     &attrType,
			     &error);
 
    }
    if (locstat == FAILURE)
	{
	ACS_SHORT_LOG((LM_INFO,"dbRead failed."));
	errDisplay(&error,ccsFALSE);
	}
    
    // ccsExit();
    return m_value;
}

void 
DevIODBRead::write(const CORBA::Double &value, int& errcode, unsigned long long& timestamp)
{
	ACS_SHORT_LOG((LM_INFO,"dbWrite not implemented."));
}



/*___oOo___*/