#nullable enable

using System;

namespace UVC.Data
{
    /// <summary>
    /// MQTT 파이프라인 정보를 관리하는 클래스입니다.
    /// MQTT 토픽 구독, 메시지 핸들링 및 데이터 매핑에 필요한 설정을 제공합니다.
    /// </summary>
    /// <remarks>
    /// 이 클래스는 빌더 패턴을 사용하여 MQTT 구독 설정을 유연하게 구성할 수 있게 합니다.
    /// 각 설정 메서드는 체이닝을 통해 파이프라인을 정의할 수 있도록 합니다.
    /// </remarks>
    /// <example>
    /// <code>
    /// var pipelineInfo = new MQTTPipeLineInfo("device/status")
    ///     .setDataMapper(new DataMapper(dataMask))
    ///     .setHandler(data => Console.WriteLine(data));
    /// </code>
    /// </example>
    public class MQTTPipeLineInfo
    {
        private string _topic; // MQTT 토픽
        private Action<IDataObject?>? _handler = null; // 메시지 핸들러
        private DataMapper? _dataMapper = null; // 데이터 매퍼
        private bool _updatedDataOnly = false; // 업데이트된 데이터만 받을 여부

        /// <summary>
        /// MQTT 토픽
        /// </summary>
        public string Topic => _topic;

        /// <summary>
        /// 메시지 핸들러
        /// </summary>
        public Action<IDataObject?>? Handler => _handler;

        /// <summary>
        /// 데이터 매퍼
        /// </summary>
        public DataMapper? DataMapper => _dataMapper;

        /// <summary>
        /// 업데이트된 데이터만 받을 여부 (true로 설정하면, 데이터가 변경된 경우에만 핸들러가 호출됩니다)
        /// </summary>
        public bool UpdatedDataOnly => _updatedDataOnly;

        /// <summary>
        /// MQTTPipeLineInfo 클래스의 새 인스턴스를 초기화합니다.
        /// </summary>
        /// <param name="topic">구독할 MQTT 토픽</param>
        /// <param name="updatedDataOnly">변경된 데이터만 처리할지 여부 (기본값: true)</param>
        /// <remarks>
        /// updatedDataOnly가 true인 경우, 이전 데이터와 동일한 메시지는 핸들러에 전달되지 않습니다.
        /// 이는 불필요한 데이터 처리를 방지하고 성능을 향상시킵니다.
        /// </remarks>
        public MQTTPipeLineInfo(string topic, bool updatedDataOnly = true)
        {
            _topic = topic;
            _updatedDataOnly = updatedDataOnly;
        }

        /// <summary>
        /// MQTT 메시지를 수신했을 때 호출될 핸들러를 설정합니다.
        /// </summary>
        /// <param name="handler">메시지 데이터를 처리할 콜백 함수</param>
        /// <returns>현재 MQTTPipeLineInfo 인스턴스 (메서드 체이닝용)</returns>
        /// <remarks>
        /// 핸들러는 메시지가 수신되고 DataMapper에 의해 변환된 후 호출됩니다.
        /// UpdatedDataOnly 속성이 true인 경우, 데이터가 변경된 경우에만 호출됩니다.
        /// </remarks>
        public MQTTPipeLineInfo setHandler(Action<IDataObject?> handler)
        {
            _handler = handler;
            return this;
        }

        /// <summary>
        /// MQTT 메시지 데이터를 처리할 데이터 매퍼를 설정합니다.
        /// </summary>
        /// <param name="dataMapper">사용할 데이터 매퍼 객체</param>
        /// <returns>현재 MQTTPipeLineInfo 인스턴스 (메서드 체이닝용)</returns>
        /// <remarks>
        /// 데이터 매퍼는 수신된 MQTT 메시지(JSON 형식)를 IDataObject로 변환하는 역할을 합니다.
        /// DataMask를 사용하여 특정 필드에 대한 타입 변환 및 필드 이름 매핑을 처리할 수 있습니다.
        /// </remarks>
        /// <example>
        /// <code>
        /// // DataMask를 사용한 데이터 매퍼 설정
        /// var dataMask = new DataMask();
        /// dataMask["temperature"] = 0.0;  // 실수 타입 지정
        /// dataMask["humidity"] = 0;      // 정수 타입 지정
        /// dataMask["timestamp"] = "";    // 문자열 타입 지정
        /// 
        /// var pipelineInfo = new MQTTPipeLineInfo("sensor/data")
        ///     .setDataMapper(new DataMapper(dataMask))
        ///     .setHandler(data => ProcessSensorData(data));
        /// </code>
        /// </example>
        public MQTTPipeLineInfo setDataMapper(DataMapper dataMapper)
        {
            _dataMapper = dataMapper;
            return this;
        }

    }
}
