using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Threading.Tasks;
using NewLife;
using NewLife.Data;
using NewLife.Log;
using NewLife.Net;
using NewLife.Net.Handlers;
using NewLife.Serialization;
using OPC_Client;

namespace ScadaTcpService
{
	public abstract class ScadaService
	{

		private static Scada _scada;
		private static TcpServer _tcpServer;
		internal static ConcurrentDictionary<int, bool> InitDic = new ConcurrentDictionary<int, bool>();
		public static void Start()
		{
			var port = ConfigurationManager.AppSettings["Port"].ToInt();
			_tcpServer = new TcpServer
			{
				Port = port,
				Log = XTrace.Log,
				SessionLog = XTrace.Log
			};
			_tcpServer.Add<StandardCodec>();
			_tcpServer.Start(); 
            CreateScada();

		}


		public static void Stop()
		{
			_scada.Stop();
			_tcpServer.Stop("");
		}

		public static List<Data> GetAllData()
		{
			return _scada.GetAllData();
		}

		private static void CreateScada()
		{
			try
			{
				var serverName = ConfigurationManager.AppSettings["ServerName"];
				var pointFile = ConfigurationManager.AppSettings["PointFile"];
				_scada = new Scada(serverName, pointFile);
				_scada.ChangeEvent += (data, changeItems) =>
				{
					if (_tcpServer.SessionCount < 1) return;
					var dataList =
						data.Where(c => changeItems.Contains(c.Key))
							.Select(c => new
							{
								c.Value.dataType,
								c.Value.itemID,
								c.Value.timeStamp,
								c.Value.batchNum,
								c.Value.id,
								c.Value.quality,
								c.Value.DateTime1,
								c.Value.value
							})
							.ToList();
                    var sendData = new
                    {
                        cmd = "sendData",
                        data = dataList
                    };
					_tcpServer.SendAllAsync(new Packet(sendData.ToJson().GetBytes()));
					//foreach (var item in InitDic.Where(c => c.Value))
					//{
					//	_tcpServer.GetSession(item.Key)?.SendMessage(new Packet(sendData.ToJson().GetBytes()));
					//}
				};
				_scada.Start();
			}
			catch (Exception e)
			{
				XTrace.WriteException(e);
			}
		}


	}
	/// <summary>定义服务端，用于管理所有网络会话</summary>
	internal class TcpServer : NetServer<TcpSession>
	{
        
    }

	/// <summary>定义会话。每一个远程连接唯一对应一个网络会话，再次重复收发信息</summary>
	internal class TcpSession : NetSession<TcpServer>
	{
		protected override void OnConnected()
		{
			if (!ScadaService.InitDic.ContainsKey(ID))
				ScadaService.InitDic.TryAdd(ID, false);
			var data = new
			{
				cmd = "getAllData",
				data = ScadaService.GetAllData().Select(c => new
				{
					c.dataType,
					c.itemID,
					c.timeStamp,
					c.batchNum,
					c.id,
					c.quality,
					c.DateTime1,
					c.value
				}).ToList()
			};
			Send(new Packet(data.ToJson().GetBytes()));
			base.OnConnected();
		}

		protected override void OnDisconnected(string reason)
		{
			if (ScadaService.InitDic.ContainsKey(ID))
				ScadaService.InitDic.Remove(ID);
			base.OnDisconnected(reason);
		}

		protected override void OnReceive(ReceivedEventArgs e)
		{
			if (!(e.Message is Packet pk)) return;
			if (pk.ToStr().ToLower().Contains("start") != true) return;
			if (ScadaService.InitDic.ContainsKey(ID))
				ScadaService.InitDic[ID] = true;

		}
	}
}