using JiShe.CollectBus.Common.Consts;
using JiShe.CollectBus.FreeRedis;
using JiShe.CollectBus.IotSystems.Protocols;
using JiShe.CollectBus.Protocol.Interfaces;
using JiShe.CollectBus.Protocol.Models;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using TouchSocket.Sockets;
using Volo.Abp.Domain.Repositories;

namespace JiShe.CollectBus.Protocol.Abstracts
{
    public abstract class ProtocolPlugin : IProtocolPlugin
    {
        //头部字节长度
        public const int hearderLen = 6;

        public const int tPLen = 6;

        public const string errorData = "EE";

        private readonly ILogger _logger;
        private readonly IRepository<ProtocolInfo, Guid> _protocolInfoRepository;
        private readonly IFreeRedisProvider _redisProvider;

        public ProtocolPlugin(IServiceProvider serviceProvider, ILogger logger)
        {
            _logger = logger;
            _protocolInfoRepository = serviceProvider.GetRequiredService<IRepository<ProtocolInfo, Guid>>();
            _redisProvider = serviceProvider.GetRequiredService<IFreeRedisProvider>();
        }


        public abstract ProtocolInfo Info { get; }

        public virtual async Task<ProtocolInfo> GetAsync() => await Task.FromResult(Info);

        public virtual async Task LoadAsync()
        {
            if (Info == null)
            {
                throw new ArgumentNullException(nameof(Info));
            }

            await _protocolInfoRepository.DeleteDirectAsync(a => a.Name == Info.Name);
            await _protocolInfoRepository.InsertAsync(Info);
            await _redisProvider.Instance.HDelAsync($"{RedisConst.ProtocolKey}", Info.Name);
            await _redisProvider.Instance.HSetAsync($"{RedisConst.ProtocolKey}", Info.Name, Info);
        }

        public abstract Task<T> AnalyzeAsync<T>(ITcpSessionClient client, string messageReceived, Action<T>? receivedAction = null) where T : class;

        #region 下行命令构建

        /// <summary>
        /// 组装报文
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entity">设备数据实体</param>
        /// <param name="afnFnCode">映射读取执行方法的Code，例如10_1，表示 10H_F1_00000,10H_F1_00001，统一英文下划线分隔</param>
        /// <returns></returns>
        public abstract Task<ProtocolBuildResponse> BuildAsync(ProtocolBuildRequest request);

        #endregion

    }
}
