using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.ServiceModel;
using System.Threading;
//using CRVM.IDExcuter;

namespace ICService
{
    // SessionMode.Required  允许Session会话
    [ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(ICallback))]
    public interface IPushMessage
    {
        //----->IsOneWay = false等待服务器完成对方法处理;
        //IsInitiating = true启动Session会话,
        //IsTerminating = false 设置服务器发送回复后不关闭会话
        [OperationContract(IsOneWay = true, IsInitiating = true, IsTerminating = false)]
        void Login(string uid);

        [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
        void Update(string uid);

        [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
        void Leave(string uid);

    }

    public interface ICallback
    {
        [OperationContract(IsOneWay = true)]
        //void ShowMsg(Machine msg);
        void ShowMsg(AllData data);
    }

    public class Client
    {
        public ICallback callback;
        public DateTime updatetime;
        public Client(ICallback callback, DateTime updatetime)
        {
            this.callback = callback;
            this.updatetime = updatetime;
        }
    }

    // InstanceContextMode.PerSession 服务器为每个客户会话创建一个新的上下文对象。ConcurrencyMode.Multiple 异步的多线程实例
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Multiple)]
    public class PushMessage : IPushMessage
    {
        static Dictionary<string, Client> dit_callback = new Dictionary<string, Client>();//创建一个静态Dictionary（表示键和值）集合(字典)，用于记录在线成员，Dictionary<(Of <(TKey, TValue>)>) 泛型类

        private static List<string> uidRemoveed = new List<string>();//记录已经断开的连接对象
        private static Object syncObj = new Object();////定义一个静态对象用于线程部份代码块的锁定，用于lock操作

        public void Login(string uid)
        {
            lock (syncObj)
            {
                dit_callback.Add(uid, new Client(OperationContext.Current.GetCallbackChannel<ICallback>(), DateTime.Now));
            }
        }

        public void Update(string uid)
        {
            lock (syncObj)
            {
                if (dit_callback.ContainsKey(uid))
                {
                    dit_callback.Remove(uid);
                }
                dit_callback.Add(uid, new Client(OperationContext.Current.GetCallbackChannel<ICallback>(), DateTime.Now));
            }
        }

        public void Leave(string uid)
        {
            lock (syncObj)
            {
                uidRemoveed.Add(uid);
            }
        }

        public static void SendMsg(AllData data)
        {
            lock (syncObj)
            {
                //Console.WriteLine("在线用户数(" + dit_callback.Count + ") 群发信息：" + msg);
                foreach (var item in dit_callback)
                {
                    try
                    {
                        //Console.WriteLine($"now time:{DateTime.Now.ToString("yyyy-mm-dd hh:mm:ss:FFF")},uid:{item.Key}");
                        if (!uidRemoveed.Contains(item.Key))
                        {
                            item.Value.callback.ShowMsg(data);
                        }
                    }
                    catch (Exception)
                    {
                        uidRemoveed.Add(item.Key);
                        Console.WriteLine("发送异常，用户=" + item.Key + "");
                    }
                }
                foreach (string item in uidRemoveed)
                {
                    dit_callback.Remove(item);
                }
                uidRemoveed.Clear();
            }

        }
    }
    public class MacDataEventArgs : EventArgs
    {
        public AllData data;
        public MacDataEventArgs(AllData data)
        {
            this.data = data;
        }
    }

    public delegate void MacDataHandle(object sender, MacDataEventArgs e);



    public class Callback : ICallback
    {
        public event MacDataHandle MacDataChanged;
        
        public void ShowMsg(AllData data)
        {
         
            if (MacDataChanged != null)
            {
                MacDataChanged.Invoke(this, new MacDataEventArgs(data));
            }
        }
    }


    [Serializable]
    public class AllData
    {

        public double[] vibData { get; set; }
        public double[] standSpeed { get; set; }
        public bool cutState { get; set; }
        public double lenthSpeed { get; set; }
        public double stripLength { get; set; }
    }

}
