
#ifndef ETHERCAT_UTILS_XML_H
#define ETHERCAT_UTILS_XML_H

#pragma once

#include "../ethercat_types.h"
#include <stdint.h>
#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif

struct dll;

#define XML_MAX_SLAVES      64
#define XML_MAX_SM          16
#define XML_MAX_PDO_ENTRIES 128
#define XML_MAX_NAME        128
#define XML_MAX_TYPE        64
#define XML_MAX_DATATYPE    32

typedef struct {
    uint16_t vlan_id;
    uint8_t  vlan_priority;
    uint8_t  frame_high_priority;
    uint8_t  enable_dscp;
    uint8_t  dscp_value;
} DarraQosConfig;

typedef struct {
    uint32_t cycle_time_us;
    uint32_t dc_cycle_ns;
    int32_t  cpu_affinity;
    uint8_t  redundancy;
    uint8_t  use_udp;
    uint8_t  mutex_protection;
    uint8_t  overlapping_groups;
    uint8_t  packed_mode;
    uint8_t  frame_repeat_count;
    uint8_t  adaptive_timeout;
    uint16_t wd_pd_timeout_ms;
    uint16_t wd_pdi_timeout_ms;
    uint32_t timeout_init_to_preop;
    uint32_t timeout_preop_to_safeop;
    uint32_t timeout_safeop_to_op;
    DarraQosConfig qos;
} DarraMasterXmlConfig;

typedef struct {
    uint8_t  index;
    uint16_t start_addr;
    uint16_t length;
    uint8_t  flags;
    uint8_t  sm_type;
    uint16_t watchdog;
} DarraSyncManagerXmlConfig;

typedef struct {
    uint16_t index;
    uint8_t  sub_index;
    uint16_t bit_length;
    char     name[XML_MAX_TYPE];
    char     data_type[XML_MAX_DATATYPE];
    uint32_t offset;
    uint16_t pdo_index;
} DarraPdoEntryXmlConfig;

typedef struct {

    uint16_t index;
    char     name[XML_MAX_NAME];
    uint32_t vendor_id;
    uint32_t product_code;
    uint32_t revision;
    uint16_t config_addr;

    uint32_t input_size;
    uint32_t output_size;
    uint32_t input_bit_size;
    uint32_t output_bit_size;

    DarraPdoEntryXmlConfig input_entries[XML_MAX_PDO_ENTRIES];
    int      input_entry_count;
    DarraPdoEntryXmlConfig output_entries[XML_MAX_PDO_ENTRIES];
    int      output_entry_count;

    uint16_t mbx_recv_offset;
    uint16_t mbx_recv_size;
    uint16_t mbx_send_offset;
    uint16_t mbx_send_size;

    uint16_t dc_assign_activate;
    uint32_t dc_cycle0;
    uint32_t dc_cycle1;
    int32_t  dc_shift0;
    int32_t  dc_shift1;

    DarraSyncManagerXmlConfig sm[XML_MAX_SM];
    int      sm_count;

    uint8_t  supports_coe;
    uint8_t  supports_soe;
    uint8_t  supports_foe;
    uint8_t  supports_eoe;
    uint8_t  supports_voe;

    uint8_t  is_optional;
} DarraSlaveXmlConfig;

typedef struct {
    int      success;
    int      config_slave_count;
    int      actual_slave_count;
    int      matched_count;
} DarraXmlConfigResult;

int deni_load(const char* path,
                    DarraMasterXmlConfig* master_out,
                    DarraSlaveXmlConfig* slaves_out,
                    int max_slaves);

int deni_save(const char* path,
                    const DarraMasterXmlConfig* master,
                    const DarraSlaveXmlConfig* slaves,
                    int slave_count);

int eni_load(const char* path,
                   DarraMasterXmlConfig* master_out,
                   DarraSlaveXmlConfig* slaves_out,
                   int max_slaves);

int eni_save(const char* path,
                   const DarraMasterXmlConfig* master,
                   const DarraSlaveXmlConfig* slaves,
                   int slave_count);

int xml_apply_config(const struct dll* dll,
                           const DarraMasterXmlConfig* master_config,
                           uint16_t master_index);

#ifdef __cplusplus
}
#endif

#endif
