/*
 * SPDX-FileCopyrightText: 2025 Copyright contributors to the cppTango project
 *
 * SPDX-License-Identifier: LGPL-3.0-or-later
 */
#ifndef TANGO_CLIENT_HELPERS_HELPERBASE_H
#define TANGO_CLIENT_HELPERS_HELPERBASE_H

#include <tango/client/DeviceProxy.h>
#include <tango/client/helpers/TangoExceptionsHelper.h>
#include <tango/server/DeviceImpl.h>
#include <tango/server/LogAdapter.h>

#include <string>

//=============================================================================
// MACRO
//=============================================================================
#define FULL_CMD_NAME(C) device_proxy_->dev_name() + "::" + C
#define FULL_ATTR_NAME(A) device_proxy_->dev_name() + "/" + A
//
//    Definition of macros to benefit from expansion of __FILE__ and __LINE__ keywords in Device caller source file
//
#define read_attribute(ATTR_NAME, VALUE) internal_read_attribute(ATTR_NAME, VALUE, __FILE__, __LINE__)
#define read_attribute_w(ATTR_NAME, VALUE) internal_read_attribute_w(ATTR_NAME, VALUE, __FILE__, __LINE__)
#define write_attribute(ATTR_NAME, VALUE) internal_write_attribute(ATTR_NAME, VALUE, __FILE__, __LINE__)
#define command(CMD_NAME) internal_command(CMD_NAME, __FILE__, __LINE__)

#if defined(__clang__)
  #pragma clang diagnostic push
  #pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
#endif

#define command_out(CMD_NAME, OUT, ...) internal_command_out(CMD_NAME, OUT, ##__VA_ARGS__, __FILE__, __LINE__)
#define command_in(CMD_NAME, IN, ...) internal_command_in(CMD_NAME, IN, ##__VA_ARGS__, __FILE__, __LINE__)
#define command_inout(CMD_NAME, ...) internal_command_inout(CMD_NAME, ##__VA_ARGS__, __FILE__, __LINE__)

#if defined(__clang__)
  #pragma clang diagnostic pop
#endif

namespace Tango
{
//=============================================================================
// CLASS: HelperBase
//=============================================================================
class HelperBase : public Tango::LogAdapter
{
  public:
    //---------------------------------------------------------------------------
    //  HelperBase::get_device_proxy
    //  returns the underlying device
    //---------------------------------------------------------------------------
    inline Tango::DeviceProxy *get_device_proxy(void)
    {
        return device_proxy_;
    }

    //---------------------------------------------------------------------------
    //  HelperBase::operator->
    //  returns the underlying device
    //---------------------------------------------------------------------------
    inline Tango::DeviceProxy *operator->(void)
    {
        return device_proxy_;
    }

  protected:
    //---------------------------------------------------------------------------
    //  HelperBase::HelperBase  (ctor)
    //  device_name : The name of the target device.
    //  client_device : Reference to the client device (for logging purpose).
    //---------------------------------------------------------------------------
    HelperBase(const std::string &device_name, Tango::DeviceImpl *client_device = 0) :
        Tango::LogAdapter(client_device),
        device_proxy_(0)
    {
        _DEV_TRY_REACTION(
            //- try
            device_proxy_ = new Tango::DeviceProxy(const_cast<std::string &>(device_name)),
            //- what do we tried
            std::string("new Tango::DeviceProxy on ") + device_name,
            //- origin
            "HelperBase::HelperBase",
            //- reaction
            if(device_proxy_) {
                delete device_proxy_;
                device_proxy_ = 0;
            });
    }

    //---------------------------------------------------------------------------
    // HelperBase::~HelperBase (dtor)
    //---------------------------------------------------------------------------
    virtual ~HelperBase()
    {
        if(device_proxy_)
        {
            delete device_proxy_;
            device_proxy_ = 0;
        }
    }

    //---------------------------------------------------------------------------
    //- the underlying device
    //---------------------------------------------------------------------------
    Tango::DeviceProxy *device_proxy_;
};

} // namespace Tango
#endif
