using FreeRedis;
using ServiceCenter.Extensions;
using System.ComponentModel;
using System.Diagnostics;
using WCS.Core;
using WCS.Entity.Protocol.BCR;
using WCS.Entity.Protocol.DataStructure;
using WCS.Entity.Protocol.Station;
using WCS.WorkEngineering.Worlds;

namespace WCS.WorkEngineering.Systems
{
    //[BelongTo(typeof(MainWorld))]
    [Description("数据采集系统")]
    public class 数据采集 : SystemBase
    {
        private RedisClient Redis = new RedisClient("");

        public 数据采集()
        {
            var gs = Device.All.SelectMany(v => v.Protocols.Select(d => new { DB = $"{d.Value.DBInfo.No}:{d.Value.DBInfo.PLCInfo.IP}", d.Value.Position, TypeStr = d.Key, Dev = v }))
                .GroupBy(v => v.DB);
            foreach (var g in gs)
            {
                var min = g.OrderBy(v => v.Position).First();
                var max = g.OrderByDescending(v => v.Position).First();
                var t = Type.GetType(min.TypeStr);
                min.Dev.Protocol(t, this.World);
                max.Dev.Protocol(t, this.World);
            }
        }

        public override List<object> GetObjects()
        {
            return new List<object>();
        }

        public override void Update(List<WorkTimes> list)
        {
            var sw = new Stopwatch();
            sw.Start();
            var pack = new DeviceDataPack();
            pack.Frame = DateTime.Now;
            var ps = pack.GetType().GetProperties().OrderBy(x => x.Name);
            foreach (var p in ps)
            {
                if (!p.PropertyType.IsArray&&p.PropertyType!= typeof(IBCR80[]))
                    continue;
                var dev = p.PropertyType.GetElementType();
                if (dev.GetInterfaces().Any(v => v.GetInterfaces().Any(d => d.Name == "IProtocol")))
                {
                    var t = p.PropertyType.GetElementType();
                    var protType = GetProtocolType(t);
                    var arr = Device.All.Where(v => v.HasProtocol(protType))
                    .Select(v =>
                    {
                        try
                        {
                            var obj = Activator.CreateInstance(t);
                            t.GetProperty("Code").SetValue(obj, v.Code);
                            dynamic protObj = v.Protocol(protType, World);
                            if (protType == typeof(IBCR81))
                            {
                                var a = new Device<IBCR81>(v, World);
                                var b = a.Data.Content;

                            }
                            var value = ServiceCenter.Extensions.TypeExtension.Copy(protObj, t);
                            //t.GetProperty("Data").SetValue(obj, value);
                            return obj;
                        }
                        catch (Exception ex)
                        {
                            return null;
                        }
                    }).Where(v => v != null).ToArray();

                    var m = typeof(Enumerable).GetMethod("OfType", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
                    m = m.MakeGenericMethod(t);
                    var arr2 = m.Invoke(null, new object[] { arr });

                    m = typeof(Enumerable).GetMethod("ToArray", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
                    m = m.MakeGenericMethod(t);
                    var arr3 = m.Invoke(null, new object[] { arr2 });
                    p.SetValue(pack, arr3);
                }
            }

            //Redis.RPush("Packs", pack);
            //if (Redis.LLen("Packs") > 50000)
            //{
            //    Redis.LTrim("Packs", 5000, -1);
            //}

            sw.Stop();
            list.Add(new WorkTimes { Total = sw.ElapsedMilliseconds, Key = "采集数据" });
            //var sw = new Stopwatch();
            //sw.Start();
            //var pack = new DeviceDataPack();
            //pack.Frame = DateTime.Now;
            //var ps = pack.GetType().GetProperties();
            //foreach (var p in ps)
            //{
            //    if (!p.PropertyType.IsClass) continue;

            //    var packAct = Activator.CreateInstance(p.PropertyType);
            //    var prs = p.PropertyType.GetProperties();
            //    foreach (var pr in prs)
            //    {
            //        if (!pr.PropertyType.IsArray) continue;

            //        var yt = pr.PropertyType.GetElementType();
            //        if (yt.IsClass)
            //        {
            //            var pros = yt.GetProperties();
            //            //var entType = yt.GetGenericArguments()[0];
            //            //var protType = GetProtocolType(entType);
            //            var dataAct = Activator.CreateInstance(yt);
            //            Parallel.ForEach(pros, pro =>
            //            {
            //                try
            //                {
            //                    if (pro.PropertyType != typeof(DateTime))
            //                    {
            //                        if (pro.PropertyType != typeof(string))
            //                        {
            //                            var protType = GetProtocolType(pro.PropertyType);
            //                            var dev = Device.All
            //                                .Where(v => v.HasProtocol(protType)).Select(v =>
            //                                {
            //                                    try
            //                                    {
            //                                        var obj = Activator.CreateInstance(pro.PropertyType);
            //                                        pro.PropertyType.GetProperty("Code").SetValue(obj, v.Code);
            //                                        var a = v.Protocol(protType, World);
            //                                        var value = v.Protocol(protType, World).Copy(pro.PropertyType);
            //                                        pro.SetValue(obj, value);
            //                                        return obj;
            //                                    }
            //                                    catch (Exception ex)
            //                                    {
            //                                        return null;
            //                                    }
            //                                }).FirstOrDefault(v => v != null);

            //                            if (dev != null)
            //                            {
            //                                pro.SetValue(dataAct, dev);
            //                            }
            //                        }
            //                        else
            //                        {
            //                        }
            //                    }
            //                }
            //                catch (Exception e)
            //                {
            //                    Console.WriteLine(e);
            //                }
            //            });

            //            var a = 1;

            //            //var m = typeof(Enumerable).GetMethod("OfType", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
            //            //m = m.MakeGenericMethod(yt);
            //            //var arr2 = m.Invoke(null, new object[] { datasAct });

            //            //m = typeof(Enumerable).GetMethod("ToArray", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
            //            //m = m.MakeGenericMethod(yt);
            //            //var arr3 = m.Invoke(null, new object[] { arr2 });
            //            //p.SetValue(pack, arr3);

            //            //var entType = yt.GetGenericArguments()[0];
            //            //var protType = GetProtocolType(entType);
            //            //var arr = Device.All.Where(v => v.HasProtocol(protType))
            //            //    .Select(v =>
            //            //    {
            //            //        try
            //            //        {
            //            //            var obj = Activator.CreateInstance(yt);
            //            //            yt.GetProperty("Code").SetValue(obj, v.Code);
            //            //            //var value = v.Protocol(protType, World).Copy(entType);
            //            //            //t.GetProperty("Data").SetValue(obj, value);
            //            //            return obj;
            //            //        }
            //            //        catch (Exception ex)
            //            //        {
            //            //            return null;
            //            //        }
            //            //    }).Where(v => v != null).ToArray();

            //            //var m = typeof(Enumerable).GetMethod("OfType", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
            //            //m = m.MakeGenericMethod(yt);
            //            //var arr2 = m.Invoke(null, new object[] { arr });

            //            //m = typeof(Enumerable).GetMethod("ToArray", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
            //            //m = m.MakeGenericMethod(yt);
            //            //var arr3 = m.Invoke(null, new object[] { arr2 });
            //            //p.SetValue(pack, arr3);
            //        }
            //    }

            //    //var t = p.PropertyType.GetElementType();
            //    //if (t.IsGenericType)
            //    //{
            //    //    var entType = t.GetGenericArguments()[0];
            //    //    var protType = GetProtocolType(entType);
            //    //    var arr = Device.All.Where(v => v.HasProtocol(protType))
            //    //    .Select(v =>
            //    //    {
            //    //        try
            //    //        {
            //    //            var obj = Activator.CreateInstance(t);
            //    //            t.GetProperty("Code").SetValue(obj, v.Code);
            //    //            //var value = v.Protocol(protType, World).Copy(entType);
            //    //            //t.GetProperty("Data").SetValue(obj, value);
            //    //            return obj;
            //    //        }
            //    //        catch (Exception ex)
            //    //        {
            //    //            return null;
            //    //        }
            //    //    }).Where(v => v != null).ToArray();

            //    //    var m = typeof(Enumerable).GetMethod("OfType", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
            //    //    m = m.MakeGenericMethod(t);
            //    //    var arr2 = m.Invoke(null, new object[] { arr });

            //    //    m = typeof(Enumerable).GetMethod("ToArray", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
            //    //    m = m.MakeGenericMethod(t);
            //    //    var arr3 = m.Invoke(null, new object[] { arr2 });
            //    //    p.SetValue(pack, arr3);
            //    //}
            //}

            ////Redis.RPush("Packs", pack);
            ////if (Redis.LLen("Packs") > 50000)
            ////{
            ////    Redis.LTrim("Packs", 5000, -1);
            ////}

            //sw.Stop();
            //list.Add(new WorkTimes { Total = sw.ElapsedMilliseconds, Key = "采集数据" });
        }

        private Type GetProtocolType(Type source)
        {
            var t = source.GetInterfaces().FirstOrDefault(v => v.GetInterfaces().Any(d => d.Name == "IProtocol"));
            return t;
        }
    }
}
