/**
 * @file CFM_Sync.h
 * @brief 时间和信息同步功能头文件
 * 
 * 该头文件定义了系统时间同步和信息同步相关的接口函数、
 * 数据结构和常量定义，为系统内各模块提供统一的时间同步服务。
 * 
 * 主要包含：
 * - 时间同步接口函数声明
 * - 信息同步相关数据结构定义
 * - 同步状态枚举和常量定义
 * - 错误码定义
 * 
 * @author [硬件平台部平台软件组]
 * @date [2025-12-01]
 * @version [1.0]
 */
#ifndef CFM_SYNC_H
#define CFM_SYNC_H 

#include "CM_Types.h"
#include "CM_Mutex.h"
#include "CM_Socket.h"
#include "CM_Atomic.h"
#include "PFM_Cfg.h"

#define CFM_MAX_DEV_NUM 100  /* 最大设备数量 暂定100 个设备 */
#define CIRCULAR_BUFFER_SIZE    (10)         /* 环形缓冲区大小 */
#define CFM_TIME_2X_COUNT (10)
#define CFM_TIME_SYNC_OBJECT   (2) //使用校时服务的功能数量，目前为2

typedef enum
{
    ENUM_TIME_ERROR = 0,     /**< 保留 */
    ENUM_TIME_START,         /**< 时钟同步开始 */
    ENUM_TIME_REQ,           /**< 时钟同步请求 */
    ENUM_TIME_ACK,           /**< 时钟同步应答 */
    ENUM_TIME_RET,           /**< 时钟同步结果返回 */
    ENUM_TIME_PEER_RESULT    /**< 对端结果 */
} ENUM_TIME_MSG_T;

/**
 * @brief 环形数组统计结构体
 *
 * 用于维护环形数组的状态信息，包括数组本身、元素计数和插入位置
 */
typedef struct
{
    CM_INT64 *pBuffer;     /**< 环形数组缓冲区指针 */
    CM_INT32 size;          /**< 环形数组大小 */
    CM_INT32 count;          /**< 数组元素计数 */
    CM_INT32 index;          /**< 当前插入位置 */
} STRU_CIRCULAR_BUFFER_T;

typedef struct
{
    CM_CHAR IP[32];  /* 源IP */
    CM_UINT16 Port;  /* 目标端口 */
}STRU_CFM_TIME_MSG_T;

typedef struct
{
    STRU_CFM_TIME_MSG_T Local_2oo2_Addr;
    STRU_CFM_TIME_MSG_T Peer_2oo2_Addr; 
    STRU_CFM_TIME_MSG_T Local_4x_Addr;
    STRU_CFM_TIME_MSG_T Partner_Addr;
    STRU_CFM_TIME_MSG_T Partner_Area_Addr_A;
    STRU_CFM_TIME_MSG_T Partner_Area_Addr_B;
}STRU_CFM_TIME_ADDR_T;

/** 时钟同步控制 */
typedef struct
{
    CM_SOCKET pSock;  /* 本地socket */

    CM_UINT8 destDev_Num; /* 目标设备数量 */
    STRU_CFM_TIME_ADDR_T time_addr; /* 时间同步地址信息 */
    STRU_CFM_TIME_MSG_T local_addr; /* 本地设备地址信息 */
    STRU_CFM_TIME_MSG_T destDev_addr[CFM_MAX_DEV_NUM]; /* 目标设备地址信息 */
    
    STRU_CIRCULAR_BUFFER_T circular_buf; /* 环形数组统计结构体 */

    CM_UINT8 time_type; /* 时间同步类型 */
    /*
    * delay和offset受互斥信号量mutex保护，
    * 读写offset时需要先取得互斥信号量
    */
    CM_MUTEX_T mutex;       /* 互斥信号量 */
    ENUM_CM_RETURN isOK;  /* 校时成功标志 */
    CM_INT64 offset;      /* 偏移时间 */
    CM_ATOMIC CM_UINT8 TimeSyncFlag; /* 时间同步标志 */
    CM_INT64 cyc_time;   /* 周期时间 */
}STRU_CFM_TIME_CTRL_T;

/**
 * @brief 获取时间偏移量并计算校时结果
 *
 * 根据时间同步类型获取相应的本地和对端时间偏移量，通过2oo2交换机制获取对端数据，
 * 并根据系统状态和预设门限计算最终的时间调整值。
 *
 * @param[out] p_avg_offset_2x 2x时间同步类型的平均偏移量输出指针
 * @param[out] p_avg_offset_2oo2 2oo2时间同步类型的平均偏移量输出指针
 *
 * @note 该函数会根据主从状态和时间偏移量大小决定是否需要调整时钟
 * @see CFM_Get_Time
 * @see SFM_2oo2_Exchange_Currency
 * @see SFM_GetLocal4x2State
 */
void CFM_Get_Offset(CM_INT64 *p_avg_offset_2x, CM_INT64 *p_avg_offset_2oo2);
/**
 * @brief 发送时间同步请求消息
 * 
 * 向2oo2和2x时间同步通道发送时间同步启动请求消息，触发时间同步过程。
 * 通过UDP协议向配置的本地地址和端口发送ENUM_TIME_START消息。
 * 
 * @param[in] void 无参数
 * 
 * @return 无
 * 
 * @note 该函数会同时向2oo2和2x两个时间同步通道发送启动请求
 * @see ENUM_TIME_START
 * @see s_TimeCtrl
 */
void CFM_SendLocalARQ(void);
/**
 * @brief 获取时间同步状态标志
 *
 * 获取系统时间同步完成状态标志，用于判断时间同步是否已完成且在有效范围内。
 * 该标志由时间同步算法根据计算出的时间偏移量与预设门限值比较后设置。
 *
 * @param[in] void 无参数
 *
 * @return CM_BOOL 时间同步状态
 * @retval CM_TRUE  时间同步完成且在允许误差范围内
 * @retval CM_FALSE 时间同步未完成或超出允许误差范围
 *
 */
CM_UINT8 CFM_GetTimeSyncFlag(void);
ENUM_CM_RETURN CFM_TimeSync_Init(IN CM_UINT8 DevNum);

/*获取本地输出比较结果，输出校验与应用跟随比较结果，比较一致返回CM_TRUE,失败返回CM_FALSE*/
CM_UINT8 CFM_GetSyncFailFlag(void);
/*获取失步次数，没有收到输出校验与应用跟随数据的周期计数*/
CM_UINT32 CFM_GetOutOfSync(void);
/*获取本地同步健康度:全部参数同步成功，离线升备，或升主条件，同步成功返回CM_TRUE,失败返回CM_FALSE*/
CM_UINT8 CFM_GetSyncHealth(void);

#endif // CFM_SYNC_H
