using DTO;
using HKCardOUT.Helper;
using HKCardOUT.Logic.Model;
using HKCardOUT.Logic.Service;
using HKCardOUT.Views;
using HKLog;
using Stylet;
using StyletIoC;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using UHFHelper;
using XExten.Advance.InternalFramework.Securities.Common;
using XExten.Advance.LinqFramework;
using XExten.Advance.StaticFramework;

namespace HKCardOUT.ViewModels
{
    public class RootViewModel : Conductor<IScreen>
    {
        public delegate void ReadCardFunc(DKoutput? input);
        public event ReadCardFunc ReadFunc;
        private IContainer Container;
        public RootViewModel(IContainer Container)
        {
            this.Container = Container;
            this.Activated += RootViewModel_Activated;
            this.Closed += RootViewModel_Closed;
            ProcessCard();
        }

        /// <summary>
        /// 关闭页面
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void RootViewModel_Closed(object sender, CloseEventArgs e)
        {
            ThreadManage.GetInstance().Dispose();
            UHF_RS485_Helper.GetInstance().Close();
        }


        private void RootViewModel_Activated(object sender, ActivationEventArgs e)
        {
            ReadFunc -= ReadCard;
            ReadFunc += ReadCard;
            ThreadManage.GetInstance().Start(new Action(() =>
            {
                while (!SerialPort.GetPortNames().Contains(DataBus.COM))
                {
                    Thread.Sleep(1000);
                }

                UHF_RS485_Helper.GetInstance().DisConnect = new Action(() =>
                {
                    ThreadManage.GetInstance().StopTask("串口监听");
                });

                UHF_RS485_Helper.GetInstance().OpenOk = new Action(() =>
                {
                    Object async = new object();
                    DataBus.StoreInfo.Devices.ForEach(item =>
                    {
                        ThreadManage.GetInstance().Start(new Action(() =>
                        {
                            try
                            {
                                while (true)
                                {
                                    if (UHF_RS485_Helper.GetInstance().GetSerialPortState())
                                    {
                                        if (DataBus.StoreInfo != null)
                                        {
                                            DKoutput res = null;
                                            //Monitor.TryEnter(async, 2000);
                                            res = UHF_RS485_Helper.GetInstance().ReadCard(item.Address.AsInt());
                                            //Monitor.Exit(async);
                                            if (res != null)
                                            {
                                                HKLog.HKLogImport.WriteInfo($"{DateTime.Now.ToString("HH:mm:ss")} 卡号地址：{res.Address}----------卡号数据：{res.ResData}");
                                                if (!res.ResData.IsNullOrEmpty()) {
                                                    if (res.ResData.Length==20)
                                                        ReadFunc?.Invoke(res);
                                                }
                                                Thread.Sleep(2000);
                                            }
                                        }
                                    }
                                    Thread.Sleep(50);
                                }
                            }
                            catch (Exception ex)
                            {
                                HKLog.HKLogImport.WriteInfo($"{DateTime.Now.ToString("HH:mm:ss")} 异常信息：{ex.Message}");
                                Monitor.Exit(async);
                            }
                        }), $"监听{item.Address}", true);
                    });
                });

                // 打开串口
                UHF_RS485_Helper.GetInstance().Open(new SerialParam
                {
                    PortName = DataBus.COM,
                    BaudRate = 57600,
                    DataBits = 8
                });
                if (!UHF_RS485_Helper.GetInstance().GetSerialPortState())
                {
                    HandyControl.Controls.Growl.InfoGlobal("串口打开失败");
                }
            }), "打开串口");

        }
        protected override void OnViewLoaded()
        {
            //广告初始化
            Task.Factory.StartNew(new Action(() =>
            {
                var Init = DataBus.StoreInfo?.Devices.Join(DataBus.StoreInfo?.Stalls, t => t.GateId, x => x.Id, (t, x) => new AdDTO
                {
                    Ad = x.Remaek,
                    Device = t.Name,
                    Stalls = x.Name
                }).ToList();
                if (Init != null)
                {
                    Ad = new ObservableCollection<AdDTO>(Init);
                    var route = SyncStatic.CreateFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AD.txt"));
                    SyncStatic.WriteFile(Encoding.UTF8.GetBytes(SyncStatic.Compress(Init.ToJson(), SecurityType.Base64)), route);
                    AdOpen();
                }
                else
                {
                    var jsons = SyncStatic.Decompress(SyncStatic.ReadFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AD.txt")), SecurityType.Base64);
                    Ad = new ObservableCollection<AdDTO>(jsons.ToModel<List<AdDTO>>());
                    AdOpen();
                }
            }));

        }

        #region 属性
        public RootView Main { get; set; }
        ObservableCollection<SaleLog> _Result;
        public ObservableCollection<SaleLog> Result
        {
            get => _Result;
            set => SetAndNotify(ref _Result, value);
        }
        ObservableCollection<AdDTO> _Ad;
        public ObservableCollection<AdDTO> Ad
        {
            get => _Ad;
            set => SetAndNotify(ref _Ad, value);
        }
        #endregion

        #region 网络检查
        private void AdOpen()
        {
            App.Current.Dispatcher.Invoke(new Action(() =>
            {
                try
                {
                    var SC = System.Windows.Forms.Screen.AllScreens.Count();
                    for (int i = 0; i < SC; i++)
                    {
                        var win = new AdWindow(Ad[i].Ad);
                        var rectangle = System.Windows.Forms.Screen.AllScreens[i].WorkingArea;
                        win.Height = rectangle.Height;
                        win.Width = rectangle.Width;
                        win.Top = 0;
                        win.Left = rectangle.Left;
                        win.Owner = this.Main;
                        win.Show();
                    }
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.ToString());
                    var win = new AdWindow("暂无广告");
                    var rectangle = System.Windows.Forms.Screen.AllScreens[0].WorkingArea;
                    win.Height = rectangle.Height;
                    win.Width = rectangle.Width;
                    win.Top = 0;
                    win.Left = rectangle.Left;
                    win.Owner = this.Main;
                    win.Show();
                }
            }));
        }

        #endregion

        private SaleLogDto prevSaleLogDto;

        #region 命令
        public void ReadCard(DKoutput input)
        {
            var mo = new SaleLogDto
            {
                CardNo = input.ResData.Substring(1, input.ResData.Length - 1),
                Location = input.Address.AsInt().ToString(),
                Date = DateTime.Now
            };
            UHF_RS485_Helper.GetInstance().OpenBeep(mo.Location.AsInt());
            HKLogImport.WriteInfo("读卡成功：" + mo.ToJson());
            if (Stacks.Count > 0)
            {
                var check = Stacks.Where(t => t.CardNo == mo.CardNo).Where(t => t.Location == mo.Location).FirstOrDefault();
                if (check == null
                    && (null != prevSaleLogDto && prevSaleLogDto.CardNo != check.CardNo)
                    )
                    Stacks.Enqueue(mo);
            }
            else
                Stacks.Enqueue(mo);
        }

        private void ProcessCard()
        {
            ThreadManage.GetInstance().StartLong(() =>
            {
                if (0 < Stacks.Count && Stacks.TryDequeue(out SaleLogDto Info))
                {
                    if (Info != null)
                    {
                        if (!HKControl.Main.GetInstance.GetIsSwipe(Info.Location.AsInt()))
                        {
                            Stacks.Enqueue(Info);
                        }
                        else
                        {
                            var Core = Container.Get<HKCore>();
                            HKLogImport.WriteInfo("队列读取成功：" + Info.ToJson());
                            if (Info.Date >= DataBus.Times.AMStartTime && Info.Date < DataBus.Times.AMEndTime)
                            {
                                Core.DeviceSaleAM(new SaleLog
                                {
                                    CardNo = Info.CardNo,
                                    Location = Info.Location,
                                    IsSync = false
                                });
                            }
                            if (Info.Date >= DataBus.Times.PMStartTime && Info.Date < DataBus.Times.PMEndTime)
                            {
                                Core.DeviceSalePM(new SaleLog
                                {
                                    CardNo = Info.CardNo,
                                    Location = Info.Location,
                                    IsSync = false
                                });

                            }
                            if (Info.Date >= DataBus.Times.ATStartTime && Info.Date < DataBus.Times.ATEndTime)
                            {
                                Core.DeviceSaleAT(new SaleLog
                                {
                                    CardNo = Info.CardNo,
                                    Location = Info.Location,
                                    IsSync = false
                                });

                            }
                        }
                    }
                }
                Thread.Sleep(50);
            }, "processCard");
        }

        private static ConcurrentQueue<SaleLogDto> Stacks = new ConcurrentQueue<SaleLogDto>();
        #endregion
    }
}
