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

#include <tango/client/DeviceData.h>

#include <vector>

namespace Tango
{
/**
 * Fundamental type for receiving data from device command polling buffers
 *
 * This is the fundamental type for receiving data from device command polling buffers. This class inherits
 * from the Tango::DeviceData class. One instance of this class is created for each command result history.
 * Within this class, you find the command result data or the exception parameters, a flag indicating if the
 * command has failed when it was invoked by the device server polling thread and the date when the command
 * was executed. For history calls, it is not possible to returns command error as exception. See chapter
 * on Advanced Features in the
 * <a href=http://www.esrf.eu/computing/cs/tango/tango_doc/kernel_doc/ds_prog/index.html target=new>Tango book</a>
 * for all details regarding device polling.
 *
 *
 * @headerfile tango.h
 * @ingroup Client
 */
class DeviceDataHistory : public DeviceData
{
  public:
    ///@privatesection
    //
    // constructor methods
    //

    DeviceDataHistory();
    DeviceDataHistory(int, int *, DevCmdHistoryList *);
    DeviceDataHistory(const DeviceDataHistory &);
    DeviceDataHistory &operator=(const DeviceDataHistory &);
    DeviceDataHistory(DeviceDataHistory &&);
    DeviceDataHistory &operator=(DeviceDataHistory &&);

    ~DeviceDataHistory() override;

    ///@publicsection
    /**
     * Check if the record was a failure
     *
     * Returns a boolean set to true if the record in the polling buffer was a failure
     *
     * @return A boolean set to true if the record was a failure
     */
    bool has_failed()
    {
        return fail;
    }

    /**
     * Get record polling date
     *
     * Returns the date when the device server polling thread has executed the command.
     *
     * @return The record polling date
     */
    TimeVal &get_date()
    {
        return time;
    }

    /**
     * Get record error stack
     *
     * Return the error stack recorded by the device server polling thread in case of the command failed when it
     * was invoked.
     *
     * @return The record error stack
     */
    const DevErrorList &get_err_stack()
    {
        return err.in();
    }

    /**
     * Print a DeviceDataHistory instance
     *
     * Is an utility function to easily print the contents of a DeviceDataHistory object. This function knows all
     * types which could be inserted in a DeviceDataHistory object and print them accordingly. It also prints date
     * and error stack in case the command returned an error.
     * @code
     * DeviceProxy *dev = new DeviceProxy(“...”);
     * int hist_depth = 4;
     * std::vector<DeviceDataHistory> *hist;
     *
     * hist = dev->command_history(“MyCommand”,hist_depth);
     *
     * for (int i = 0;i < hist_depth;i++)
     * {
     *    std::cout << (*hist)[i] << std::endl;
     * }
     * delete hist;
     * @endcode
     *
     * @param [in] str The printing stream
     * @param [in] ddh The instance to be printed
     */
    friend std::ostream &operator<<(std::ostream &str, const DeviceDataHistory &ddh);

    ///@privatesection
    // Three following methods for compatibility with older release

    bool failed()
    {
        return fail;
    }

    void failed(bool val)
    {
        fail = val;
    }

    void set_date(TimeVal &tv)
    {
        time = tv;
    }

    TimeVal &date()
    {
        return time;
    }

    const DevErrorList &errors()
    {
        return err.in();
    }

    void errors(DevErrorList_var &del)
    {
        err = del;
    }

  protected:
    ///@privatesection
    bool fail;
    TimeVal time;
    DevErrorList_var err;

    DevCmdHistoryList *seq_ptr;
    int *ref_ctr_ptr;

  private:
    class DeviceDataHistoryExt
    {
      public:
        DeviceDataHistoryExt() { }
    };

    std::unique_ptr<DeviceDataHistoryExt> ext_hist;
};

using DeviceDataHistoryList = std::vector<DeviceDataHistory>;

} // namespace Tango
#endif
