using DbCommon.BusinessCore.BaseCore;
using DbCommon.Enties.DbModels;
using Newtonsoft.Json;
using Pms.DataLibrary.Order;
using Pms.Models;
using ProjectManagementSystem.Common.Extenions;
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 AsyncBehavior
    {
        private static ConcurrentDictionary<string, string> tempLog = new ConcurrentDictionary<string, string>();

        private AsyncBehaviorManager asyncBehaviorManager = new AsyncBehaviorManager();

        public Guid Id { get; set; }

        public int Behavior { get; set; }
        public int Interval { get; set; } = 1000;
        public string TaskID { get; set; }
        public int MaxStepId { get; set; }

        public bool FirstStart { get; set; }

        public void Init()
        {
            Id = Guid.NewGuid();

            var mode = new AsyncBehaviorModel();
            mode.Id = Id;
            mode.TaskID = TaskID;
            mode.Behavior = Behavior;
            mode.Interval = Interval;
            mode.MaxStepId = MaxStepId;
            mode.FirstStart = FirstStart;

            mode.AssemblyString = this.GetType().Assembly.GetName().Name;
            mode.FullClassName = this.GetType().FullName;

            asyncBehaviorManager.Insert(mode);
        }

        public void Start()
        {
            Task.Factory.StartNew(BehaviorProc);
        }

        public bool IsRollerRotation(TaskData taskData, StepData stepInfo)
        {
            var agvData = PmsApi.GetCarrier(taskData.Carrier);
            if (agvData == null)
            {
                Log(taskData, stepInfo, "获取AGV数据失败");
                return false;
            }

            //判断AGV滚筒是否已经转动
            var logicBits = agvData.LogicBits;
            bool rollerMoveing = (logicBits & (0x01 << 7)) > 0;
            if (!rollerMoveing)
            {
                Log(taskData, stepInfo, $"等待AGV滚筒转动，LogicBits：{logicBits}");
                return false;
            }

            return true;
        }

        public void BehaviorProc()
        {
            FirstStart = true;
            CLog.Instance.TaskLog.WriteInfo($"{TaskID} {Behavior} 【异步】启动 检测间隔{Interval}ms 最大步骤{MaxStepId}");
            while (true)
            {
                try
                {
                    var taskData = PmsApi.GetTaskData(TaskID);
                    if (taskData == null)
                    {
                        var hisTaskData = PmsApi.GetHistoryTaskData(TaskID);
                        if (hisTaskData != null)
                        {
                            CLog.Instance.TaskLog.WriteInfo($"{TaskID} {Behavior} 【异步】获取到历史任务信息，异步行为码完成");
                            break;
                        }

                        CLog.Instance.TaskLog.WriteInfo($"{TaskID} {Behavior} 【异步】获取当前任务信息失败，再次尝试...");
                        continue;
                    }
                    var stepInfo = taskData.GetCurrentStepInfo();

                    if (FirstStart
                        && FirstOperator(taskData, stepInfo))
                    {
                        FirstStart = false;
                    }

                    if (taskData.CurrentStepID > MaxStepId)
                    {
                        Log(taskData, stepInfo, $"当前任务步骤为{taskData.CurrentStepID} 大于 {MaxStepId}，行为码完成（跳出）");
                        break;
                    }

                    if (!FirstStart)
                    {
                        if (CustomOperator(taskData, stepInfo))
                        {
                            Log(taskData, stepInfo, "正常完成");
                            break;
                        }
                    }


                }
                catch (Exception ex)
                {
                    CLog.Instance.TaskLog.WriteException("AsyncBehavior", ex);
                    Thread.Sleep(5000);
                }

                Thread.Sleep(Interval);
            }

            asyncBehaviorManager.Delete(Id);
        }

        public virtual bool FirstOperator(TaskData taskData, StepData stepInfo)
        {
            return true;
        }

        public virtual bool CustomOperator(TaskData taskData, StepData stepInfo)
        {
            return true;
        }

        private static bool CheckLogRepeat(string taskId, string log)
        {
            bool result = tempLog.ContainsKey(taskId) ? tempLog[taskId] == log : false;

            tempLog.AddOrUpdate(taskId, log, (key, vaule) => log);
            return result;
        }

        public static void Log(TaskData taskData, StepData stepData, string log)
        {
            string strLog = $"{taskData.TaskID} Step{taskData.CurrentStepID} {stepData.PmsBehavior} {stepData.AgvBehavior} {taskData.Carrier}# {stepData.WareHouseID} {log}";

            if (CheckLogRepeat(taskData.TaskID, log)) return;

            CLog.Instance.GetAgvLog(taskData.Carrier).WriteInfo($"【异步】{strLog}");
        }
    }
}
