using DbCommon.BusinessCore.BaseCore;
using DbCommon.Enties.DbModels;
using ProjectManagementSystem.Common.Config;
using ProjectManagementSystem.Common.Extenions;
using ProjectManagementSystem.Common.Function;
using ProjectManagementSystem.Common.Logger;
using ProjectManagementSystem.Common.WebApi;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ProjectManagementSystem.Common.Core
{
    public class RouteCalled
    {
        private static RouteCalled m_instance;
        private ConcurrentQueue<RouteCalledInfo> m_calledRoute = new ConcurrentQueue<RouteCalledInfo>();
        private LocationPropertyManager m_locationManager = new LocationPropertyManager();
        private CallTaskManager callTaskManager = new CallTaskManager();

        private ConcurrentDictionary<int, DateTime> routeCallTimeDict = new ConcurrentDictionary<int, DateTime>();
        private int coldTime = 60;

        private int[] lesRoutes = AppSetting.TryGetValue<string>("LesCallBoxRoutes").ToValueArray<int>();

        public static RouteCalled Instance
        {
            get
            {
                if (m_instance == null)
                {
                    m_instance = new RouteCalled();
                }
                return m_instance;
            }
        }

        private RouteCalled()
        {
            Task.Factory.StartNew(UserThread);
        }

        public void Call(int route, bool called, bool cancelCall, string taskType = "")
        {
            m_calledRoute.Enqueue(new RouteCalledInfo() { Route = route, Called = called, CancelCalled = cancelCall, TaskType = taskType });
        }

        public void RouteProc()
        {
            while (m_calledRoute.TryDequeue(out RouteCalledInfo infoBox))
            {
                CLog.Instance.SystemLog.WriteInfo($"线路{infoBox.Route} 叫料:{infoBox.Called} 叫料取消:{infoBox.CancelCalled}");

                int route = infoBox.Route;
                if (!lesRoutes.Contains(route))
                {
                    continue;
                }

                routeCallTimeDict.TryGetValue(route, out var clickTime);
                if (clickTime != null)
                {
                    var totalSec = (DateTime.Now - clickTime).TotalSeconds;
                    if (totalSec <= coldTime)
                    {
                        CLog.Instance.SystemLog.WriteInfo($"线路{infoBox.Route} 未到冷却时间{coldTime}s忽略处理 距离上次上报LES成功{totalSec:F1}s");
                        continue;
                    }
                }

                var routeConfig = ExcelConfig.Instance.RouteConfigList.Find(d => d.LesRoutes.Contains(route));

                if (routeConfig != null
                    && !string.IsNullOrEmpty(routeConfig.LocationCode))
                {
                    if (infoBox.Called)
                    {
                        int idx = routeConfig.LesRoutes.ToList().IndexOf(route);
                        string podTyp = routeConfig.LesPodTypes.Length > idx ? routeConfig.LesPodTypes[idx] : null;

                        bool result = false;

                        if (string.IsNullOrEmpty(podTyp))
                        {
                            result = CustomerApi.AgvAndonRequestApi(new Models.RequestAgvAndonRequestApi() { buttonId = route.ToString() }, out string content);
                        }
                        else
                        {
                            var data = new Models.RequestAgvEmptyBoxReqApi()
                            {
                                location = routeConfig.LocationCode,
                                podTyp = podTyp
                            };

                            result = CustomerApi.AgvEmptyBoxReqApi(data, out string content);
                        }

                        //上报成功灭灯
                        if (result)
                        {
                            for (int j = 0; j < 5; j++)
                            {
                                DeviceControl.Instance.CallBoxLightOff(route);
                                Thread.Sleep(200);
                            }

                            routeCallTimeDict.AddOrUpdate(route, DateTime.Now, (k, v) => DateTime.Now);
                        }
                        else
                        {
                            CLog.Instance.SystemLog.WriteInfo($"线路{infoBox.Route} 上报LES不成功");
                        }

                        ////上传不成功，报警灯提示
                        //int lightId = 10;
                        //int lightType = result? 1 : 0;
                        //DeviceControl.Instance.SetAlarmLight(lightId, lightType);
                    }

                }
                else
                {
                    //没有配置路线
                    if (infoBox.Called)
                    {
                        var result = CustomerApi.AgvAndonRequestApi(new Models.RequestAgvAndonRequestApi() { buttonId = route.ToString() }, out string content);

                        if (result)
                        {
                            for (int j = 0; j < 5; j++)
                            {
                                DeviceControl.Instance.CallBoxLightOff(route);
                                Thread.Sleep(200);
                            }

                            routeCallTimeDict.AddOrUpdate(route, DateTime.Now, (k, v) => DateTime.Now);
                        }
                        else
                        {
                            CLog.Instance.SystemLog.WriteInfo($"线路{infoBox.Route} 按灯上报LES不成功");
                        }

                        ////上传不成功，报警灯提示
                        //int lightId = 10;
                        //int lightType = result ? 1 : 0;
                        //DeviceControl.Instance.SetAlarmLight(lightId, lightType);
                    }
                }
            }
        }



        private void UserThread()
        {
            CLog.Instance.SystemLog.WriteDebug($"RouteCalled已启动");
            byte conter = 0;
            while (true)
            {
                try
                {
                    RouteProc();
                }
                catch (Exception ex)
                {
                    CLog.Instance.SystemLog.WriteException("RouteCalled", ex);
                    Thread.Sleep(5000);
                }

                conter++;
                Thread.Sleep(100);
            }
        }
    }

    public class RouteCalledInfo
    {
        public int Route { get; set; }
        public bool Called { get; set; }
        public bool CancelCalled { get; set; }
        public string TaskType { get; set; }
    }
}
