/*
 * SPDX-FileCopyrightText: 2004 Copyright contributors to the cppTango project
 *
 * SPDX-License-Identifier: LGPL-3.0-or-later
 */

#ifndef TANGO_INTERNAL_CLIENT_DEVAPI_MACROS_H
#define TANGO_INTERNAL_CLIENT_DEVAPI_MACROS_H

#include <tango/client/ApiExcept.h>
#include <tango/client/CallBackThread.h>
#include <tango/client/Connection.h>
#include <tango/client/DeviceAttribute.h>
#include <tango/client/DeviceData.h>
#include <tango/client/DevicePipe.h>
#include <tango/client/LockThread.h>
#include <tango/common/defines.h>
#include <tango/common/tango_const.h>
#include <tango/server/ReadersWritersLock.h>

#include <map>
#include <ostream>
#include <string>

namespace Tango
{

#define READ_ATT_EXCEPT(NAME_CHAR, OBJ)                                                                 \
    catch(Tango::ConnectionFailed & e)                                                                  \
    {                                                                                                   \
        TangoSys_OMemStream desc;                                                                       \
        desc << "Failed to read_attribute on device " << device_name;                                   \
        desc << ", attribute " << NAME_CHAR << std::ends;                                               \
        TANGO_RETHROW_DETAILED_EXCEPTION(ApiConnExcept, e, API_AttributeFailed, desc.str());            \
    }                                                                                                   \
    catch(Tango::DevFailed & e)                                                                         \
    {                                                                                                   \
        TangoSys_OMemStream desc;                                                                       \
        desc << "Failed to read_attribute on device " << device_name;                                   \
        desc << ", attribute " << NAME_CHAR << std::ends;                                               \
        TANGO_RETHROW_EXCEPTION(e, API_AttributeFailed, desc.str());                                    \
    }                                                                                                   \
    catch(CORBA::TRANSIENT & trans)                                                                     \
    {                                                                                                   \
        TRANSIENT_NOT_EXIST_EXCEPT(trans, "DeviceProxy", "read_attribute", OBJ);                        \
    }                                                                                                   \
    catch(CORBA::OBJECT_NOT_EXIST & one)                                                                \
    {                                                                                                   \
        if(one.minor() == omni::OBJECT_NOT_EXIST_NoMatch || one.minor() == 0)                           \
        {                                                                                               \
            TRANSIENT_NOT_EXIST_EXCEPT(one, "DeviceProxy", "read_attribute", OBJ);                      \
        }                                                                                               \
        else                                                                                            \
        {                                                                                               \
            set_connection_state(CONNECTION_NOTOK);                                                     \
            TangoSys_OMemStream desc;                                                                   \
            desc << "Failed to read_attribute on device " << device_name << std::ends;                  \
            TANGO_RETHROW_DETAILED_EXCEPTION(ApiCommExcept, one, API_CommunicationFailed, desc.str());  \
        }                                                                                               \
    }                                                                                                   \
    catch(CORBA::COMM_FAILURE & comm)                                                                   \
    {                                                                                                   \
        if(comm.minor() == omni::COMM_FAILURE_WaitingForReply)                                          \
        {                                                                                               \
            TRANSIENT_NOT_EXIST_EXCEPT(comm, "DeviceProxy", "read_attribute", OBJ);                     \
        }                                                                                               \
        else                                                                                            \
        {                                                                                               \
            set_connection_state(CONNECTION_NOTOK);                                                     \
            TangoSys_OMemStream desc;                                                                   \
            desc << "Failed to read_attribute on device " << device_name << std::ends;                  \
            TANGO_RETHROW_DETAILED_EXCEPTION(ApiCommExcept, comm, API_CommunicationFailed, desc.str()); \
        }                                                                                               \
    }                                                                                                   \
    catch(CORBA::SystemException & ce)                                                                  \
    {                                                                                                   \
        set_connection_state(CONNECTION_NOTOK);                                                         \
        TangoSys_OMemStream desc;                                                                       \
        desc << "Failed to read_attribute on device " << device_name << std::ends;                      \
        TANGO_RETHROW_DETAILED_EXCEPTION(ApiCommExcept, ce, API_CommunicationFailed, desc.str());       \
    }

#define COPY_BASE_CONFIG(A, B)                           \
    A[i].name = B[i].name;                               \
    A[i].writable = B[i].writable;                       \
    A[i].data_format = B[i].data_format;                 \
    A[i].data_type = B[i].data_type;                     \
    A[i].max_dim_x = B[i].max_dim_x;                     \
    A[i].max_dim_y = B[i].max_dim_y;                     \
    A[i].description = B[i].description;                 \
    A[i].label = B[i].label;                             \
    A[i].unit = B[i].unit;                               \
    A[i].standard_unit = B[i].standard_unit;             \
    A[i].display_unit = B[i].display_unit;               \
    A[i].format = B[i].format;                           \
    A[i].min_value = B[i].min_value;                     \
    A[i].max_value = B[i].max_value;                     \
    A[i].writable_attr_name = B[i].writable_attr_name;   \
    A[i].extensions.resize(B[i].extensions.length());    \
    for(size_t j = 0; j < B[i].extensions.length(); j++) \
    {                                                    \
        A[i].extensions[j] = B[i].extensions[j];         \
    }

#define COPY_ALARM_CONFIG(A, B)                                        \
    A[i].alarms.min_alarm = B[i].att_alarm.min_alarm;                  \
    A[i].alarms.max_alarm = B[i].att_alarm.max_alarm;                  \
    A[i].alarms.min_warning = B[i].att_alarm.min_warning;              \
    A[i].alarms.max_warning = B[i].att_alarm.max_warning;              \
    A[i].alarms.delta_t = B[i].att_alarm.delta_t;                      \
    A[i].alarms.delta_val = B[i].att_alarm.delta_val;                  \
    A[i].alarms.extensions.resize(B[i].att_alarm.extensions.length()); \
    for(size_t j = 0; j < B[i].att_alarm.extensions.length(); j++)     \
    {                                                                  \
        A[i].alarms.extensions[j] = B[i].att_alarm.extensions[j];      \
    }

#define COPY_EVENT_CONFIG(A, B)                                                               \
    A[i].events.ch_event.rel_change = B[i].event_prop.ch_event.rel_change;                    \
    A[i].events.ch_event.abs_change = B[i].event_prop.ch_event.abs_change;                    \
    A[i].events.ch_event.extensions.resize(B[i].event_prop.ch_event.extensions.length());     \
    for(size_t j = 0; j < B[i].event_prop.ch_event.extensions.length(); j++)                  \
    {                                                                                         \
        A[i].events.ch_event.extensions[j] = B[i].event_prop.ch_event.extensions[j];          \
    }                                                                                         \
                                                                                              \
    A[i].events.per_event.period = B[i].event_prop.per_event.period;                          \
    A[i].events.per_event.extensions.resize(B[i].event_prop.per_event.extensions.length());   \
    for(size_t j = 0; j < B[i].event_prop.per_event.extensions.length(); j++)                 \
    {                                                                                         \
        A[i].events.per_event.extensions[j] = B[i].event_prop.per_event.extensions[j];        \
    }                                                                                         \
                                                                                              \
    A[i].events.arch_event.archive_rel_change = B[i].event_prop.arch_event.rel_change;        \
    A[i].events.arch_event.archive_abs_change = B[i].event_prop.arch_event.abs_change;        \
    A[i].events.arch_event.archive_period = B[i].event_prop.arch_event.period;                \
    A[i].events.arch_event.extensions.resize(B[i].event_prop.arch_event.extensions.length()); \
    for(size_t j = 0; j < B[i].event_prop.arch_event.extensions.length(); j++)                \
    {                                                                                         \
        A[i].events.arch_event.extensions[j] = B[i].event_prop.arch_event.extensions[j];      \
    }

} // namespace Tango

#endif /* TANGO_INTERNAL_CLIENT_DEVAPI_MACROS_H */
