using Aitex.Core.RT.Log;
using Aitex.Core.Util;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Aitex.Core.RT.DataCenter;

namespace Aitex.Core.RT.DataCollection.HighPerformance
{
    /// <summary>
    /// 数据收集器对象，用于收集在<see cref="DataManager"/>中注册的数据源的数据。
    /// </summary>
    public class DataBuffer<T> : IDataBuffer
    {
        #region Variables

        private readonly Dictionary<long, string> _buffer = new ();
        private readonly R_TRIG _rTrigReadFailed = new ();

        #endregion

        #region Constructors

        public DataBuffer(int index, string name, Func<object> read)
        {
            Index = index;
            Name = name;
            Read = read;
        }

        #endregion

        #region Properties

        /// <summary>
        /// 返回数据获取器的序号。
        /// </summary>
        public int Index { get; }

        /// <summary>
        /// 返回数据获取器名称。
        /// </summary>
        public string Name { get; }

        public Type ValueType => typeof(T);
        
        /// <summary>
        /// 返回数据获取器。
        /// </summary>
        public Func<object> Read{ get; }

        /// <summary>
        /// 返回缓存数据的长度。
        /// </summary>
        internal int CacheCount => _buffer.Count;

        #endregion

        #region Methods

        private string ReadAndFormatValue()
        {
            try
            {
                var value = (T)Read.Invoke();
                return DataTraceHelper.Format(value);
            }
            catch (Exception ex)
            {
                Debug.Assert(false, $"Unable to cache data [{Name}], {ex.Message}");
                return "'0'";
            }
        }

        /// <summary>
        /// 缓存数据。
        /// </summary>
        /// <param name="timestamp"></param>
        public void Cache(long timestamp)
        {
            try
            {
                _buffer[timestamp] = ReadAndFormatValue();
                _rTrigReadFailed.CLK = false;
            }
            catch (Exception ex)
            {
                // 首次发生错误时记录日志。
                _rTrigReadFailed.CLK = true;
                if(_rTrigReadFailed.Q)
                    LOG.Error($"数据获取器 {Name} 在 {timestamp} 时发生错误。", ex);

                _buffer[timestamp] = string.Empty;
            }
        }

        /// <summary>
        /// 获取指定时间戳的数据。
        /// </summary>
        /// <param name="timestamp">时间戳。</param>
        /// <returns></returns>
        public string Get(long timestamp)
        {
            if (_buffer.TryGetValue(timestamp, out var value))
            {
                _buffer.Remove(timestamp);
                return value;
            }
            else
            {
                return default;
            }
        }

        public override string ToString()
        {
            return $"[{Index}] {Name}, {ValueType.Name}";
        }

        #endregion
    }
}
