using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using MQTTnet;
using MQTTnet.Protocol;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Ropin.IOT.MqttService.RequestModel;
using Ropin.Inspection.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace Ropin.IOT.MqttService.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class ValueController : ControllerBase
    {
        private readonly ILogger<ValueController> _logger;
        private readonly MqttOptions _mqttOptions;
        public IMemoryCache _memoryCache;

        public ValueController(ILogger<ValueController> logger, IMemoryCache memoryCache, MqttOptions mqttOptions)
        {
            _logger = logger;
            _memoryCache = memoryCache;
            _mqttOptions = mqttOptions;
        }
        
        public class TdevDevicePointSearchModel
        {
            public string[] groupnames { get; set; }
            public string[] names { get; set; }
            public int timeOut { get; set; } = 600;

        }
        //public class DeviceCommandModel
        //{
        //    public string Topic { get; set; }
        //    public string Command { get; set; }
        //    public int timeOut { get; set; } = 600;

        //}
        public class DevPointValue
        {
            public string id { get; set; }
            public string timestamp { get; set; }
            public string dataType { get; set; }
            public string name { get; set; }
            public string value { get; set; }
            public string status { get; set; }
            public string boxId { get; set; }
            public string connState { get; set; }
            public string connStateTimestamp { get; set; }

        }
        [HttpPost("GetDevicePointByAsync")]
        public async Task<IList<DevPointValue>> GetDevicePointByAsync([FromQuery] string boxNo, [FromBody]TdevDevicePointSearchModel searchModel)
        {
            //if (searchModel == null)
            //{
            //    return new ApiResult(ReturnCode.ArgsError);
            //}
            //searchModel.IsPagination = false;
            if (MqttClientService._mqttDevicePointNameMappingDic == null || MqttClientService._mqttDevicePointDic == null)
            {
                return null;
            }
            IList< DevPointValue> devPoints = new List<DevPointValue>();
            try
            {
                for(int i =0;i< searchModel.names.Length;i++)
                {
                    string name = searchModel.names[i];
                    string groupname = searchModel.groupnames[i];
                    if (!MqttClientService._mqttDevicePointNameMappingDic.ContainsKey(boxNo + groupname + name))
                    {
                        devPoints.Add(null);
                        continue;
                    }
                    string englishname = MqttClientService._mqttDevicePointNameMappingDic[boxNo + groupname + name];
                    MqttDevicePoint mqttDevicePoint;
                    MqttClientService._mqttDevicePointDic.TryGetValue(englishname,out mqttDevicePoint);
                    if (mqttDevicePoint!=null)
                    devPoints.Add(new DevPointValue {
                        id = mqttDevicePoint.Id,
                        timestamp= mqttDevicePoint.UpLoadTime.ToString("yyyy-MM-dd HH:mm:ss"),
                        dataType = mqttDevicePoint.DataType,
                        name = mqttDevicePoint.ChineseName,
                        value = mqttDevicePoint.Value,
                        status = mqttDevicePoint.BoxStatus,
                        boxId = mqttDevicePoint.BoxId,
                        connState="1",
                        connStateTimestamp = mqttDevicePoint.UpLoadTime.ToString("yyyy-MM-dd HH:mm:ss"),
                    });
                }
                return devPoints;

            }
            catch (Exception ex)
            {
                //return new ApiResult(ReturnCode.GeneralError, ex.Message);
                return null;
            }
        }
        /// <summary>
        /// 发送命令到设备
        /// </summary>
        /// <param name="boxNo"></param>
        /// <param name="searchModel"></param>
        /// <returns></returns>
        [HttpPost("PublishDeviceCommandByAsync")]
        public async Task<bool> PublishDeviceCommandByAsync([FromQuery] string boxNo, [FromBody] DeviceCommandModel model)
        {
           
            //if (searchModel == null)
            //{
            //    return new ApiResult(ReturnCode.ArgsError);
            //}
            //searchModel.IsPagination = false;
            try
            {
                Task.Factory.StartNew(async () =>
                {
                    var msg = new MqttApplicationMessage()
                    {
                        Topic = model.Topic,
                        Payload = Encoding.UTF8.GetBytes(model.Command),
                        QualityOfServiceLevel =
                            (MqttQualityOfServiceLevel)
                                Enum.Parse(typeof(MqttQualityOfServiceLevel), MqttQualityOfServiceLevel.AtLeastOnce.ToString()),
                        Retain = false
                    };
                    if (null != MqttClientService._mqttClient)
                    {
                        await MqttClientService._mqttClient.PublishAsync(msg);
                    }
                });
                return await Task.FromResult(true);
            }
            catch (Exception ex)
            {
                //return new ApiResult(ReturnCode.GeneralError, ex.Message);
                return await Task.FromResult(false);
            }
        }
        [HttpPost("Get")]
        public object Get([FromQuery]string boxNo, [FromBody] QueryModel model)
        {
            _memoryCache.Set("001", "{\"boxId\": \"001\",     \"data\": [         {             \"name\": \"gzzs\",             \"value\": \"DO1\"         },         {             \"name\": \"bj\",             \"value\": \"DO2\"         },         {             \"name\": \"zs\",             \"value\": \"AI1\"         },         {             \"name\": \"wd\",             \"value\": \"AI2\"         },         {             \"name\": \"fcnd\",             \"value\": \"AI3\"         },         {             \"name\": \"vocs\",             \"value\": \"AI4\"         },         {             \"name\": \"fs\",             \"value\": \"AI5\"         },         {             \"name\": \"sd\",             \"value\": \"AI5\"         }     ] }");
            var jsonConfigs=JsonConvert.DeserializeObject<List<JsonConfig>>(_mqttOptions.JsonConfig);
            var message= _memoryCache.Get(boxNo)?.ToString();
            if (!string.IsNullOrEmpty(message))
            {
                MqttMessage mqttMessage = JsonConvert.DeserializeObject<MqttMessage>(message);
                var queryAble= jsonConfigs.Join(mqttMessage.Data, a => a.Name, b => b.Name, (a, b) => new { a, b })
                    //.Where(x => x.a.BoxId == boxNo)
                    .Select(x => new
                    {
                        x.a.Group,
                        BoxId=boxNo,
                        x.a.Name,
                        x.a.DataType,
                        x.b.Value,
                    }).AsQueryable();
                if (model.Names.Any())
                {
                    queryAble = queryAble.Where(x => model.Names.Contains(x.Name));
                }
                if (model.Groupnames.Any())
                {
                    queryAble = queryAble.Where(x => model.Groupnames.Contains(x.Group));
                }
                var result=queryAble.ToList();
                return result;
            }
            return new object();
        }
    }
}