/*
 * SPDX-FileCopyrightText: 2025 Copyright contributors to the cppTango project
 *
 * SPDX-License-Identifier: LGPL-3.0-or-later
 */
#include <tango/client/DevIntrChangeEventData.h>

#include <tango/internal/client/devapi_macros.h>
#include <tango/internal/client/event_helpers.h>

#include <tango/server/tango_clock.h>

#include <chrono>

namespace Tango
{

//+----------------------------------------------------------------------
//
//  DevIntrChangeEventData constructor
//
//-----------------------------------------------------------------------

DevIntrChangeEventData::DevIntrChangeEventData(DeviceProxy *dev,
                                               const std::string &evt,
                                               const std::string &d_name,
                                               DevCmdInfoList_2 *c_list,
                                               AttributeConfigList_5 *a_list,
                                               bool d_s,
                                               Tango::EventReason event_reason_in,
                                               const DevErrorList &errors_in) :
    event(evt),
    device_name(d_name),
    dev_started(d_s),
    event_reason(event_reason_in),
    errors(errors_in)
{
    TANGO_ASSERT(ensure_failure_reason_with_errors(event_reason, errors));

    device = dev;

    err = errors.length() != 0;

    if(!err && c_list != nullptr && a_list != nullptr)
    {
        //
        // Convert first command list and then attribute list
        //

        cmd_list.resize(c_list->length());
        for(size_t i = 0; i < c_list->length(); i++)
        {
            cmd_list[i].cmd_name = (*c_list)[i].cmd_name;
            cmd_list[i].cmd_tag = (*c_list)[i].cmd_tag;
            cmd_list[i].in_type = (*c_list)[i].in_type;
            cmd_list[i].out_type = (*c_list)[i].out_type;
            cmd_list[i].in_type_desc = (*c_list)[i].in_type_desc.in();
            cmd_list[i].out_type_desc = (*c_list)[i].out_type_desc.in();
            cmd_list[i].disp_level = (*c_list)[i].level;
        }

        att_list.resize(a_list->length());
        AttributeConfigList_5_var a_list_var(a_list);

        for(size_t i = 0; i < a_list->length(); i++)
        {
            COPY_BASE_CONFIG(att_list, a_list_var)

            for(size_t j = 0; j < (*a_list)[i].sys_extensions.length(); j++)
            {
                att_list[i].sys_extensions[j] = (*a_list)[i].sys_extensions[j];
            }
            att_list[i].disp_level = (*a_list)[i].level;
            att_list[i].min_alarm = (*a_list)[i].att_alarm.min_alarm;
            att_list[i].max_alarm = (*a_list)[i].att_alarm.max_alarm;
            att_list[i].root_attr_name = (*a_list)[i].root_attr_name;
            if(!(*a_list)[i].memorized)
            {
                att_list[i].memorized = NONE;
            }
            else
            {
                if(!(*a_list)[i].mem_init)
                {
                    att_list[i].memorized = MEMORIZED;
                }
                else
                {
                    att_list[i].memorized = MEMORIZED_WRITE_INIT;
                }
            }

            COPY_ALARM_CONFIG(att_list, a_list_var)

            COPY_EVENT_CONFIG(att_list, a_list_var)
        }

        a_list_var._retn();
    }

    set_time();
}

DevIntrChangeEventData::DevIntrChangeEventData(DeviceProxy *dev,
                                               const std::string &evt,
                                               const std::string &d_name,
                                               CommandInfoList *c_list,
                                               AttributeInfoListEx *a_list,
                                               bool d_s,
                                               Tango::EventReason event_reason_in,
                                               const DevErrorList &errors_in) :
    event(evt),
    device_name(d_name),
    dev_started(d_s),
    event_reason(event_reason_in),
    errors(errors_in)
{
    TANGO_ASSERT(ensure_failure_reason_with_errors(event_reason, errors));

    device = dev;

    err = errors.length() != 0;

    if(!err && c_list != nullptr && a_list != nullptr)
    {
        cmd_list = *c_list;
        att_list = *a_list;
    }

    set_time();
}

//+----------------------------------------------------------------------
//
//  DevIntrChangeEventData copy constructor
//
//-----------------------------------------------------------------------

DevIntrChangeEventData::DevIntrChangeEventData(const DevIntrChangeEventData &sou)
{
    device = sou.device;
    event = sou.event;
    device_name = sou.device_name;
    cmd_list = sou.cmd_list;
    att_list = sou.att_list;
    dev_started = sou.dev_started;
    reception_date = sou.reception_date;
    err = sou.err;
    errors = sou.errors;
    event_reason = sou.event_reason;
}

//+----------------------------------------------------------------------
//
//     DevIntrChangeEventData assignement operator
//
//-----------------------------------------------------------------------

DevIntrChangeEventData &DevIntrChangeEventData::operator=(const DevIntrChangeEventData &ri)
{
    if(&ri == this)
    {
        return *this;
    }

    device = ri.device;
    event = ri.event;
    device_name = ri.device_name;
    cmd_list = ri.cmd_list;
    att_list = ri.att_list;
    dev_started = ri.dev_started;
    reception_date = ri.reception_date;

    err = ri.err;
    errors = ri.errors;
    event_reason = ri.event_reason;

    return *this;
}

//+-------------------------------------------------------------------------
//
// method :         DevIntrChangeEventData::set_time
//
// description :     Set the event reception data
//
//--------------------------------------------------------------------------

void DevIntrChangeEventData::set_time()
{
    reception_date = make_TimeVal(std::chrono::system_clock::now());
}

} // namespace Tango
