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

#ifndef TANGO_CLIENT_GROUPDEVICEELEMENT_H
#define TANGO_CLIENT_GROUPDEVICEELEMENT_H

#include <tango/client/AsynchRequest.h>
#include <tango/client/DeviceProxy.h>
#include <tango/client/GroupAttrReplyList.h>
#include <tango/client/GroupCmdReplyList.h>
#include <tango/client/GroupElement.h>
#include <tango/client/GroupReplyList.h>

#include <vector>

namespace Tango
{

//=============================================================================
// class GroupDeviceElement: a device element
//=============================================================================
// NOLINTNEXTLINE(cppcoreguidelines-virtual-class-destructor)
class GroupDeviceElement : public GroupElement
{
    friend class Group;
    friend class GroupElementFactory;

  public:
    //---------------------------------------------
    //- Group management
    //---------------------------------------------
    //-
    DeviceProxy *get_device(const std::string &n) override;
    //-
    DeviceProxy *get_device(long idx) override;
    //-
    DeviceProxy *operator[](long idx) override;

    //---------------------------------------------
    //- a la DeviceProxy interface
    //---------------------------------------------
    //-
    bool ping(bool fwd = true) override;
    //-
    void set_timeout_millis(int tmo_ms) override;

    //---------------------------------------------
    //- Misc
    //---------------------------------------------
    //-
    void dump(int indent_level = 0) override;
    //-
    void dump(TangoSys_OMemStream &oms, int indent_level = 0) override;
    //-
    bool is_connected() override;

  private:
    //- the device proxy
    DeviceProxy *dp;
    //- asynch request repository
    AsynchRequestRep arp;

    //- forbidden methods
    GroupDeviceElement();
    GroupDeviceElement(const GroupDeviceElement &);
    GroupDeviceElement &operator=(const GroupDeviceElement &);

    //- ctor: creates an GroupDeviceElement named <name>
    GroupDeviceElement(const std::string &name);
    //- ctor: creates a GroupDeviceElement named <name> with timeout set to tmo_ms milliseconds
    GroupDeviceElement(const std::string &name, int tmo_ms);
    //- dtor: release resources
    ~GroupDeviceElement() override;

    //- build connection to the device (may throw DevFailed)
    DeviceProxy *connect();
    //- close connection
    void disconnect();

    //- a trick to get a valid device proxy or an exception
    DeviceProxy *dev_proxy()
    {
        return dp != nullptr ? dp : connect();
    }

    //- element identification
    bool is_device_i() override;
    bool is_group_i() override;

    //- size (group interface)
    long get_size_i(bool fwd = true) override;

    //- private part of the asynch impl
    long command_inout_asynch_i(const std::string &c, bool fgt, bool fwd, long ari) override;
    long command_inout_asynch_i(const std::string &c, const DeviceData &d, bool fgt, bool fwd, long ari) override;
    GroupCmdReplyList command_inout_reply_i(long req_id, long tmo_ms) override;

    long read_attribute_asynch_i(const std::string &a, bool fwd, long ari) override;
    GroupAttrReplyList read_attribute_reply_i(long req_id, long tmo_ms) override;

    long read_attributes_asynch_i(const std::vector<std::string> &al, bool fwd, long ari) override;
    GroupAttrReplyList read_attributes_reply_i(long req_id, long tmo_ms) override;

    long write_attribute_asynch_i(const DeviceAttribute &d, bool fwd, long ari) override;
    GroupReplyList write_attribute_reply_i(long req_id, long tmo_ms) override;
};

} // namespace Tango

#endif /* TANGO_CLIENT_GROUPDEVICEELEMENT_H */
