using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using parkMonitor.LOG;
using parkMonitor.entity;
using parkMonitor.model;
using System.Configuration;
using System.Threading;
using parkMonitor.server.uiLogServer;
using parkMonitor.tools;

using parkMonitor.Database2;
using MySql.Data.MySqlClient;
using parkMonitor.server.CoreThread;
using parkMonitor.server.broadcastModule;

namespace parkMonitor.server.CoreThread
{
    class CoreThreadTest2 : IEquipments, ICoreThreadDoWorking
    {
        int equipmentStatus_address;//设备总控状态地址
        bool initialized = false;
        /// <summary>
        /// 获取PLC句柄
        /// </summary>
        IEquipments PLC;
        /// <summary>
        /// 获取队列句柄
        /// </summary>
        IEquipments queuingThread;
        /// <summary>
        /// 获取号牌句柄
        /// </summary>
        IEquipments NumMachine;
        bool isClosing;

        string[] equipNames = new string[] { EquipmentName.PLC, EquipmentName.NumMachine, EquipmentName.Web, EquipmentName.Queue };

        public CoreThreadTest2()
        {
            try
            {
                EntityForCore.ins.globalStatus = false;
                equipmentStatus_address = Convert.ToInt32(ConfigurationManager.AppSettings["equipmentStatus_address"]);
            }
            catch (Exception) { }
        }

        public void Start()
        {
            BroadcastLinker.Start();
            //创建所有实例
            for (int i = 0; i < equipNames.Length; ++i)
            {
                IEquipments equip = EquipmentSimpleFactory.ins.CreateEquipment(equipNames[i]);
            }
            //启动所有实例
            for (int i = 0; i < equipNames.Length; ++i)
            {
                IEquipments equip = EquipmentSimpleFactory.ins.FindEquipment(equipNames[i]);
                equip.Start();
            }
            PLC = EquipmentSimpleFactory.ins.FindEquipment(EquipmentName.PLC);
            queuingThread = EquipmentSimpleFactory.ins.FindEquipment(EquipmentName.Queue);
            NumMachine = EquipmentSimpleFactory.ins.FindEquipment(EquipmentName.NumMachine);
            if (!(EntityForCore.ins.globalStatus = EntityForCore.ins.Init()))
            {
                UILogServer.ins.error("系统初始化异常，请检查配置");
            }
            initialized = true;
            //BeginWorking();
            //监听总状态改变消息
            //由监控线程发出
            AsyncCmdServer.ins.listen(AsyncCmdType.TotalStatusChanged, (AlarmStatus type) =>
            {
                if (type != AlarmStatus.Normal)
                {
                    hangUp();
                }
            });
        }

        public AbstractMessage GetMessage()
        {
            return null;
        }

        public void SetMessage(AbstractMessage message)
        {
        }

        public void Stop()
        {
            for (int i = 0; i < equipNames.Length; ++i)
            {
                IEquipments equip = EquipmentSimpleFactory.ins.FindEquipment(equipNames[i]);
                if (equip != null)
                {
                    equip.Stop();
                }
            }
            AbstractCmd.isClosing = true;//停止运行中指令
            this.isClosing = true;

        }
        /// <summary>
        /// 核心线程工作
        /// </summary>
        public void BeginWorking()
        {
            Timer checkRemoteTimer = new System.Threading.Timer(CheckRemotePool, null, 3600000, 3600000);
            //Timer killTimeoutConnection = new System.Threading.Timer(KillTimeoutConnection, null, 3600000, 3600000);
            //Timer checkLocalTimer = new System.Threading.Timer(CheckLocalPool, null, 10000, 300000);
            //Timer logTimer = new System.Threading.Timer(displayLog, null, 1000, 30000);
            while (!isClosing)
            {
                if (initialized && EntityForCore.ins.globalStatus)
                {
                    Command queueCmd = null;
                    //等待号牌资源
                    Task getCmd = Task.Factory.StartNew(() =>
                    {
                        while (true)
                        {
                            if (EntityForCore.ins.globalStatus)
                            {
                                //UILogServer.ins.info("停车流程：鄂A11111未获取激光数据，继续等待");
                                //UILogServer.ins.error("激光1计算异常，重新测量");
                                //UILogServer.ins.error("激光1计算异常超过重测次数，请检查");
                                //UILogServer.ins.error("鄂A11111缓冲位已满");
                                //UILogServer.ins.info("无空闲机械手资源，继续等待");
                                //UILogServer.ins.info("未获取轮距雷达完成状态，继续等待");
                                //UILogServer.ins.info("停车流程：鄂A11111未获得停车完成信号1，继续等待");
                                //UILogServer.ins.info("停车流程：鄂A11111未获得停车完成信号0，继续等待");

                                //UILogServer.ins.error("无法获取车辆信息");
                                //UILogServer.ins.error("车位分配出现异常！！！");
                                //UILogServer.ins.info("取车流程：鄂A11111未获得取车完成信号1，继续等待");
                                //UILogServer.ins.info("取车流程：鄂A11111未获得取车完成信号0，继续等待");

                                //UILogServer.ins.warn("从web收到无法识别的用户指令,并非停取车");
                                //UILogServer.ins.error("用户指令异常");

                                //UILogServer.ins.log("用户1指令鄂A11111已存在超过10.1分钟 ,强制出队");
                                //UILogServer.ins.log("号牌 鄂A11111 已扫描超过10.1分钟 ,强制出队");

                                queueCmd = (Command)queuingThread.GetMessage();
                                if (queueCmd != null)
                                {
                                    //远端或本地异常，遇到相应指令则退回
                                    if ((!queueCmd.manual && ConnectionPoolManager.malfunctionRemote) || (queueCmd.manual && ConnectionPoolManager.malfunctionLocal))
                                    {
                                        queueCmd.returnedCount = 1;
                                        queuingThread.SetMessage((Command)queueCmd.Clone());
                                        Thread.Sleep(5000);
                                        continue;
                                    }
                                    //判断当前计数是否允许线程创建，机械手资源争抢严重则将指令丢回队列
                                    else if (queueCmd.id / 6 + 1 == Robot.robot1.id)
                                    {
                                        if ((queueCmd.commandType == 's' && Robot.robot1.parkWaitCount >= 1) || (queueCmd.commandType == 'f' && Robot.robot1.fetchWaitCount >= 1))
                                        {
                                            Log.WriteLog(LogType.NOT_DATABASE, LogFile.LOG, "等待机械手1资源线程过多:" + Robot.robot1.parkWaitCount + "," + Robot.robot1.fetchWaitCount);
                                            queueCmd.returnedCount = 10000;
                                            queuingThread.SetMessage((Command)queueCmd.Clone());
                                            Thread.Sleep(5000);
                                            continue;
                                        }
                                    }
                                    else if (queueCmd.id / 6 + 1 == Robot.robot2.id)
                                    {
                                        if ((queueCmd.commandType == 's' && Robot.robot2.parkWaitCount >= 1) || (queueCmd.commandType == 'f' && Robot.robot2.fetchWaitCount >= 1))
                                        {
                                            Log.WriteLog(LogType.NOT_DATABASE, LogFile.LOG, "等待机械手2资源线程过多:" + Robot.robot2.parkWaitCount + "," + Robot.robot2.fetchWaitCount);
                                            queueCmd.returnedCount = 10000;
                                            queuingThread.SetMessage((Command)queueCmd.Clone());
                                            Thread.Sleep(5000);
                                            continue;
                                        }
                                    }
                                    break;
                                }
                            }Thread.Sleep(2000);
                        }
                    });
                    Task.WaitAll(getCmd);
                    //等待系统总状态
                    Task getSysStatus = Task.Factory.StartNew(() =>
                    {
                        GetTotalStatus();
                    });
                    Task.WaitAll(getSysStatus);
                    //对依赖同一机械手的线程计数
                    if (queueCmd.id / 6 + 1 == Robot.robot1.id)
                    {
                        if (queueCmd.commandType == 's')
                        {
                            Robot.robot1.parkWaitCount += 1;
                        }
                        else if (queueCmd.commandType == 'f')
                        {
                            Robot.robot1.fetchWaitCount += 1;
                        }
                    }
                    else if (queueCmd.id / 6 + 1 == Robot.robot2.id)
                    {
                        if (queueCmd.commandType == 's')
                        {
                            Robot.robot2.parkWaitCount += 1;
                        }
                        else if (queueCmd.commandType == 'f')
                        {
                            Robot.robot2.fetchWaitCount += 1;
                        }
                    }
                    Log.WriteLog(LogType.NOT_DATABASE, LogFile.LOG, "---线程创建:" + queueCmd.LicenseNum + "准备，等待机械手1资源停取线程计数:" + Robot.robot1.parkWaitCount + "," + Robot.robot1.fetchWaitCount);
                    Task t = Task.Factory.StartNew(() =>
                    {
                        Log.WriteLog(LogType.NOT_DATABASE, LogFile.LOG, "---线程创建:" + queueCmd.LicenseNum + "开始");
                        SimpleCMDFactory simpleCMDFactory = new SimpleCMDFactory();
                        AbstractCmd abstractCmd = simpleCMDFactory.createCmd(queueCmd);
                        abstractCmd.executeCmd(queueCmd);
                        Log.WriteLog(LogType.NOT_DATABASE, LogFile.LOG, "---线程创建:" + queueCmd.LicenseNum + "完成");
                    });
                    if (t != null)
                    {
                        Log.WriteLog(LogType.NOT_DATABASE, LogFile.LOG, "---线程创建:" + queueCmd.LicenseNum + "状态：" + t.Status);
                    }
                    else
                    {
                        Log.WriteLog(LogType.NOT_DATABASE, LogFile.LOG, "---线程创建:" + queueCmd.LicenseNum + "为空");
                    }

                }
                Thread.Sleep(300);
            }
        }

        /// <summary>挂起</summary>
        public void hangUp()
        {

        }
        /// <summary>
        /// 获取PLC总控状态
        /// </summary>
        private void GetTotalStatus()
        {
            PLCMessage PLCMsg = null;
            int normalStatus = 0;
            while (!isClosing)
            {
                PLCMsg = (PLCMessage)PLC.GetMessage();
                if (PLCMsg != null && PLCMsg.originalPlcList != null && PLCMsg.originalPlcList.Count != 0)
                {
                    normalStatus = Convert.ToInt32(PLCMsg.originalPlcList[equipmentStatus_address].Value);
                }
                //设备总控状态
                if (normalStatus == 1 && EntityForCore.ins.globalStatus)
                {
                    UILogServer.ins.log("设备总状态正常");
                    Log.WriteLog(LogType.NOT_DATABASE, LogFile.LOG, "设备总状态正常");
                    break;
                }
                Thread.Sleep(200);
            }
        }

        /// <summary>
        ///  执行日志文件数据库操作
        /// </summary>
        /// <param name="o"></param>
        private void displayLog(object o)
        {
            while (!EntityForCore.ins.globalStatus)
            {
                Thread.Sleep(1000);
            }
            lock (Parking_Space.spaceLock)
            {
                string sqlStatus;
                string sqlMsg;
                int count;
                Log.ReadLog(out sqlStatus, out sqlMsg, out count);
                List<string> strs = new List<string>();
                strs.Add(sqlMsg);
                if (count > 0)
                {
                    if (sqlStatus == "1")
                    {
                        int parkingRecordsID = 0;
                        try
                        {
                            //Operation.MyTransaction(EntityForCore.remoteBQ,sqlMsg, out parkingRecordsID);
                            parkingRecordsID = DBOperation.InsertParkingRecords(EntityForCore.remoteBQ, strs);
                            if (parkingRecordsID == 0)
                            {
                                Log.WriteLog(LogType.DATABASE, sqlStatus + ":" + sqlMsg);
                            }
                        }
                        catch
                        {
                            Log.WriteLog(LogType.DATABASE, sqlStatus + ":" + sqlMsg);
                            //throw;
                        }
                    }
                    if (sqlStatus == "0")
                    {
                        bool result;
                        try
                        {
                            //Operation.MyTransaction(EntityForCore.remoteBQ,sqlMsg, out temp); 
                            result = DBOperation.UpdateTransaction(EntityForCore.remoteBQ, strs);
                            if (!result)
                            {
                                Log.WriteLog(LogType.DATABASE, sqlStatus + ":" + sqlMsg);
                            }
                        }
                        catch
                        {
                            Log.WriteLog(LogType.DATABASE, sqlStatus + ":" + sqlMsg);
                            //throw;
                        }
                    }
                    Log.ReadLog(out sqlStatus, out sqlMsg, out count);
                }
            }
        }
        private void CheckRemotePool(object o)
        {
            ConnectionPoolManager.CheckConnPooling(3, 10, ConnectionPoolManager.remoteConf, EntityForCore.remoteBQ);
        }
        private void CheckLocalPool(object o)
        {
            ConnectionPoolManager.CheckConnPooling(3, 10, ConnectionPoolManager.localConf, EntityForCore.localBQ);
        }
        private void KillTimeoutConnection(object o)
        {
            DBOperation.KillTimeOutConnection(null, 3600, EntityForCore.remoteBQ);
            ConnectionPoolManager.CheckConnPooling(3, 10, ConnectionPoolManager.remoteConf, EntityForCore.remoteBQ);
        }
    }
}
