using Aitex.Core.Common;
using Aitex.Core.RT.Log;
using Aitex.Core.Util;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.Jobs;
using MECF.Framework.Common.RecipeCenter;
using MECF.Framework.Common.SubstrateTrackings;
using MECF.Framework.Common.WaferHolder;
using CyberX8_RT.Modules.PUF;
using CyberX8_RT.Modules;
using CyberX8_RT.Schedulers;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Markup;
using Aitex.Core.RT.SCCore;

namespace CyberX8_RT.Dispatch
{
    public class WaferTaskManager : Singleton<WaferTaskManager>
    {
        #region 常量
        private const string SIDE_A = "SideA";
        private const string SIDE_B = "SideB";
        #endregion

        #region 内部变量
        /// <summary>
        /// FA回复
        /// </summary>
        private SchedulerFACallback _schedulerFACallback = new SchedulerFACallback();
        /// <summary>
        /// 任务锁
        /// </summary>
        private object _taskLocker = new object();
        /// <summary>
        /// 任务集合
        /// </summary>
        private List<WaferTask> _waferTaskList = new List<WaferTask>();
        /// <summary>
        /// Wafer task字典
        /// </summary>
        private ConcurrentDictionary<string, WaferTask> _waferTasksDic = new ConcurrentDictionary<string, WaferTask>();
        /// <summary>
        /// Wafer配对字典(key-自身WaferId,value-配对WaferId)
        /// </summary>
        private ConcurrentDictionary<string, string> _waferTaskMatchDic = new ConcurrentDictionary<string, string>();
        /// <summary>
        /// Wafer--WaferHolder任务字典(key-自身WaferId,value-WaferHolder任务)
        /// </summary>
        private ConcurrentDictionary<string, WaferHolderTask> _waferWaferHolderTaskDic = new ConcurrentDictionary<string, WaferHolderTask>();
        #endregion

        /// <summary>
        /// 初始化Task
        /// </summary>
        /// <param name="task"></param>
        public void InitializeTask(WaferTask task)
        {
            _waferTasksDic[task.WaferId] = task;
            lock(_taskLocker)
            {
                _waferTaskList.Add(task);
            }
        }
        /// <summary>
        /// 获取WaferTask
        /// </summary>
        /// <param name="waferId"></param>
        /// <returns></returns>
        public WaferTask GetWaferTask(string waferId)
        {
            return _waferTasksDic.ContainsKey(waferId) ? _waferTasksDic[waferId] : null;
        }
        /// <summary>
        /// 是否包含
        /// </summary>
        /// <param name="waferId"></param>
        /// <returns></returns>
        public bool Contains(string waferId)
        {
            return _waferTasksDic.ContainsKey(waferId);
        }
        /// <summary>
        /// 移除任务
        /// </summary>
        /// <param name="waferId"></param>
        public void RemoveWaferTask(string waferId)
        {
            if(_waferTasksDic.ContainsKey(waferId))
            {
                _waferTasksDic.TryRemove(waferId, out var task);
                task.Dispose();
                task.OnTaskComplete -= WaferTask_OnTaskComplete;
                LOG.WriteBackgroundLog(eEvent.EV_SCHEDULER, "Scheduler", $"remove wafer {waferId} task");
            }
            if(_waferTaskMatchDic.ContainsKey(waferId))
            {
                _waferTaskMatchDic.TryRemove(waferId,out var taskMath);
            }
            lock(_taskLocker)
            {
                int index = _waferTaskList.FindIndex(O => O.WaferId == waferId);
                if (index >= 0)
                {
                    _waferTaskList.RemoveAt(index);
                }
            }
        }
        /// <summary>
        /// 加载Wafer Task集合
        /// </summary>
        /// <returns></returns>
        public List<WaferTask> LoadWaferTaskList()
        {
            return _waferTaskList.ToList(); 
        }

        /// <summary>
        /// 创建Wafer任务
        /// </summary>
        public int CreateWaferTask(List<ProcessJobInfo> processJobInfos, WaferHolderInfo waferHolderInfo,WaferHolderTask waferHolderTask)
        {
            int count = 0;
            string mateWaferTask = "";
            List<WaferInfo> wafers = new List<WaferInfo>();
            if (processJobInfos.Count == 0)
            {
                return 0;
            }
            for(int i=0; i<processJobInfos.Count;i++)
            {
                ProcessJobInfo processJobInfo = processJobInfos[i];
                for(int j=0;j< processJobInfo.SlotWafers.Count; j++)
                {
                    var item = processJobInfo.SlotWafers[j];
                    if (WaferManager.Instance.CheckHasWafer(item.Item1, item.Item2))
                    {
                        WaferInfo waferInfo = WaferManager.Instance.GetWafer(item.Item1, item.Item2);
                        if (waferInfo != null && waferInfo.ProcessState == EnumWaferProcessStatus.Idle)
                        {
                            if (!Contains(waferInfo.WaferID))
                            {
                                if (count == 0)
                                {
                                    wafers.Add(waferInfo);
                                    count++;
                                }
                                else
                                {
                                    wafers.Add(waferInfo);
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            SequenceRecipe sequenceRecipe = processJobInfos[0].SequenceRecipe;
            if (wafers.Count == 1)
            {
                WaferInfo waferInfo = wafers[0];
                ModuleName pufModuleName = ModuleName.PUF1;
                string waferSide = "";
                string dummySide = "";
                bool lastSingleWaferToSideB = sequenceRecipe.LastSingleWaferToSideB;
                if (lastSingleWaferToSideB)
                {
                    if (CheckLoaderHasSameWaferSize())
                    {
                        waferSide = SIDE_B;
                        dummySide = SIDE_A;
                    }
                    else
                    {
                        string side = AnalyseLoadSide(sequenceRecipe);
                        waferSide = side;
                        dummySide = side;
                    }
                }
                else
                {
                    if (CheckLoaderHasSameWaferSize())
                    {
                        waferSide = SIDE_A;
                        dummySide = SIDE_B;
                    }
                    else
                    {
                        string side = AnalyseLoadSide(sequenceRecipe);
                        waferSide = side;
                        dummySide = side;
                    }
                }
                if (CheckWaferHolderHasSameTypeWafers(waferHolderInfo))
                {
                    List<WaferInfo> dummyWafers = DummyWaferManager.Instance.LoadDummyWafersByWaferHolder(waferHolderInfo);
                    if (dummyWafers.Count != 0)
                    {
                        CreateWaferTaskSchedulerSequence(waferInfo, pufModuleName, waferHolderInfo, waferInfo.ProcessJob.SequenceRecipe, "",waferSide);
                        WaferInfo dummyInfo = null;
                        if (dummyWafers.Count > 1)
                        {
                            foreach (WaferInfo info in dummyWafers)
                            {
                                //最后一片Wafer使用B面,那么dummy片使用0 slot
                                if (lastSingleWaferToSideB && info.OriginSlot == 0)
                                {
                                    dummyInfo = info;
                                    break;
                                }
                                //最后一片Wafer使用A面,那么dummy片使用1 slot
                                if (!lastSingleWaferToSideB && info.OriginSlot == 1)
                                {
                                    dummyInfo = info;
                                    break;
                                }
                            }
                            if (dummyInfo == null)
                            {
                                dummyInfo = dummyWafers[0];
                            }
                        }
                        else
                        {
                            dummyInfo = dummyWafers[0];
                        }
                        CreateDummyWaferTaskSchedulerSequence(waferHolderInfo.SequenceRecipe, dummyInfo, pufModuleName, waferInfo.WaferID,dummySide);
                        _waferTaskMatchDic[waferInfo.WaferID] = dummyWafers[0].WaferID;
                        _waferTaskMatchDic[dummyWafers[0].WaferID] = waferInfo.WaferID;
                        _waferWaferHolderTaskDic[waferInfo.WaferID] = waferHolderTask;
                        _waferWaferHolderTaskDic[dummyWafers[0].WaferID] = waferHolderTask;
                        return 2;
                    }
                    else
                    {
                        CreateWaferTaskSchedulerSequence(waferInfo, pufModuleName, waferHolderInfo, waferInfo.ProcessJob.SequenceRecipe, "",waferSide);
                        _waferWaferHolderTaskDic[waferInfo.WaferID] = waferHolderTask;
                        return 1;
                    }
                }
                else
                {
                    CreateWaferTaskSchedulerSequence(waferInfo, pufModuleName, waferHolderInfo, waferInfo.ProcessJob.SequenceRecipe, "",waferSide);
                    _waferWaferHolderTaskDic[waferInfo.WaferID] = waferHolderTask;
                    return 1;
                }
            }
            else if (wafers.Count >= 2)
            {
                for (int i = 0; i < 2; i++)
                {
                    WaferInfo waferInfo = wafers[i];
                    ModuleName pufModuleName = ModuleName.PUF1;
                    if (i == 0)
                    {
                        mateWaferTask = wafers[0].WaferID;
                        if (CheckLoaderHasSameWaferSize())
                        {
                            CreateWaferTaskSchedulerSequence(waferInfo, pufModuleName, waferHolderInfo, waferInfo.ProcessJob.SequenceRecipe, "", SIDE_A);
                        }
                        else
                        {
                            string side = AnalyseLoadSide(sequenceRecipe);
                            CreateWaferTaskSchedulerSequence(waferInfo, pufModuleName, waferHolderInfo, waferInfo.ProcessJob.SequenceRecipe, "", side);
                        }
                    }
                    else
                    {
                        if (CheckLoaderHasSameWaferSize())
                        {
                            CreateWaferTaskSchedulerSequence(waferInfo, pufModuleName, waferHolderInfo, waferInfo.ProcessJob.SequenceRecipe, mateWaferTask, SIDE_B);
                        }
                        else
                        {
                            string side = AnalyseLoadSide(sequenceRecipe); 
                            CreateWaferTaskSchedulerSequence(waferInfo, pufModuleName, waferHolderInfo, waferInfo.ProcessJob.SequenceRecipe, mateWaferTask, side);
                        }
                    }
                }
                _waferTaskMatchDic[wafers[0].WaferID] = wafers[1].WaferID;
                _waferTaskMatchDic[wafers[1].WaferID] = wafers[0].WaferID;
                _waferWaferHolderTaskDic[wafers[0].WaferID] = waferHolderTask;
                _waferWaferHolderTaskDic[wafers[1].WaferID] = waferHolderTask;
                return 2;
            }
            return 0;
        }
        /// <summary>
        /// 检验Loader两边是不是尺寸一致
        /// </summary>
        /// <returns></returns>
        private bool CheckLoaderHasSameWaferSize()
        {
            int sideAWaferSize = SC.GetValue<int>($"Loader1.SideAWaferSize");
            int sideBWaferSize = SC.GetValue<int>($"Loader1.SideBWaferSize");
            return sideAWaferSize == sideBWaferSize;
        }
        /// <summary>
        /// Loader两边尺寸不一致,解析Loader使用side
        /// </summary>
        /// <param name="recipe"></param>
        /// <returns></returns>
        private string AnalyseLoadSide(SequenceRecipe recipe)
        {
            int sideAWaferSize = SC.GetValue<int>($"Loader1.SideAWaferSize");
            int sideBWaferSize = SC.GetValue<int>($"Loader1.SideBWaferSize");
            if (sideAWaferSize != sideBWaferSize)
            {
                if(recipe.SubstrateSize==sideAWaferSize)
                {
                    return SIDE_A;
                }
                else
                {
                    return SIDE_B;
                }
            }
            return "";
        }
        /// <summary>
        /// 检验WaferHolder是否存在两片生产片
        /// </summary>
        /// <param name="waferHolderInfo"></param>
        /// <returns></returns>
        private bool CheckWaferHolderHasSameTypeWafers(WaferHolderInfo waferHolderInfo)
        {
            int count = 0;
            WaferInfo waferAInfo = WaferManager.Instance.GetWaferByWaferId(waferHolderInfo.WaferAId);
            WaferType waferType = WaferType.Production;
            if (waferAInfo != null)
            {
                waferType = waferAInfo.WaferType;
                count++;
            }
            WaferInfo waferBInfo = WaferManager.Instance.GetWaferByWaferId(waferHolderInfo.WaferBId);
            if (waferBInfo != null)
            {
                if (waferBInfo.WaferType == waferType)
                {
                    count++;
                }
            }
            return count >= 2;
        }
        /// <summary>
        /// 检验WaferHolder是否存在两片生产片
        /// </summary>
        /// <param name="waferHolderInfo"></param>
        /// <returns></returns>
        private bool CheckWaferHolderHasTwoProductionWafers(WaferHolderInfo waferHolderInfo)
        {
            int count = 0;
            WaferInfo waferAInfo = WaferManager.Instance.GetWaferByWaferId(waferHolderInfo.WaferAId);
            if (waferAInfo != null && waferAInfo.WaferType==WaferType.Production)
            {
                count++;
            }
            WaferInfo waferBInfo = WaferManager.Instance.GetWaferByWaferId(waferHolderInfo.WaferBId);
            if (waferBInfo != null && waferBInfo.WaferType == WaferType.Production)
            {
                count++;
            }
            return count >= 2;
        }
        /// <summary>
        /// 创建WaferTask SchedulerSequence
        /// </summary>
        /// <param name="waferInfo"></param>
        /// <param name="pufModuleName"></param>
        /// <param name="waferHolderInfo"></param>
        /// <param name="sequenceRecipe"></param>
        private void CreateWaferTaskSchedulerSequence(WaferInfo waferInfo, ModuleName pufModuleName, WaferHolderInfo waferHolderInfo, SequenceRecipe sequenceRecipe, string mateWafeTask,string side)
        {
            List<SchedulerSequence> sequences = SchedulerSequenceManager.Instance.AnalyWaferAllSchedulerSequence(waferInfo, pufModuleName,side, waferHolderInfo, sequenceRecipe);
            PUFEntity pufEntity = Singleton<RouteManager>.Instance.GetModule<PUFEntity>(pufModuleName.ToString());
            WaferTask waferTask = new WaferTask(waferInfo, pufEntity, sequences);
            if (!string.IsNullOrEmpty(mateWafeTask))
            {
                waferTask.MateWaferTask = mateWafeTask;
            }
            waferTask.OnTaskComplete += WaferTask_OnTaskComplete;
            LOG.WriteLog(eEvent.EV_SEQUENCE, "Scheduler", $"Create wafer {waferInfo.WaferID} task");
            InitializeTask(waferTask);
        }
        /// <summary>
        /// 创建DummyWaferTask
        /// </summary>
        /// <param name="waferInfos"></param>
        public int CreateDummyWaferTask(List<WaferInfo> waferInfos,SequenceRecipe sequenceRecipe,WaferHolderTask waferHolderTask)
        {
            string mateWaferTask = "";
            int waferCount = 0;
            for (int i = 0; i < waferInfos.Count; i++)
            {
                WaferInfo waferInfo = waferInfos[i];
                int orginalSlot = waferInfo.OriginSlot;
                ModuleName pufModuleName = ModuleName.PUF1;
                string side = orginalSlot == 0 ? SIDE_A : SIDE_B;
                if(!CheckLoaderHasSameWaferSize())
                {
                    side = AnalyseLoadSide(sequenceRecipe);
                }
                waferCount = i;
                if (!Contains(waferInfo.WaferID))
                {
                    if (i == 0)
                    {
                        mateWaferTask = waferInfo.WaferID;
                        CreateDummyWaferTaskSchedulerSequence(sequenceRecipe,waferInfo, pufModuleName,"", side);
                        _waferWaferHolderTaskDic[waferInfo.WaferID] = waferHolderTask;
                    }
                    else
                    {
                        CreateDummyWaferTaskSchedulerSequence(sequenceRecipe,waferInfo, pufModuleName, mateWaferTask,side);
                        _waferTaskMatchDic[mateWaferTask] = waferInfo.WaferID;
                        _waferTaskMatchDic[waferInfo.WaferID] = mateWaferTask;
                        _waferWaferHolderTaskDic[waferInfo.WaferID]= waferHolderTask;
                        break;
                    }
                }
            }
            return waferCount + 1;
        }
        /// <summary>
        /// 创建Dummy Wafer Task 调度工序
        /// </summary>
        /// <param name="waferInfo"></param>
        /// <param name="pufModuleName"></param>
        /// <param name="mateWaferTask"></param>
        private void CreateDummyWaferTaskSchedulerSequence(SequenceRecipe sequenceRecipe,WaferInfo waferInfo,ModuleName pufModuleName,string mateWaferTask,string side)
        {
            List<SchedulerSequence> sequences = SchedulerSequenceManager.Instance.AnalyDummyWaferAllSchedulerSequence(sequenceRecipe,waferInfo,pufModuleName, side);
            PUFEntity pufEntity = Singleton<RouteManager>.Instance.GetModule<PUFEntity>(pufModuleName.ToString());
            WaferTask waferTask = new WaferTask(waferInfo, pufEntity,sequences);
            if (!string.IsNullOrEmpty(mateWaferTask))
            {
                waferTask.MateWaferTask = mateWaferTask;
            }
            LOG.WriteLog(eEvent.EV_SEQUENCE, "Scheduler", $"Create Dummy wafer {waferInfo.WaferID} task");
            waferTask.OnTaskStart += WaferTask_OnTaskStart;
            waferTask.OnTaskComplete += WaferTask_OnTaskComplete;
            InitializeTask(waferTask);
        }
        /// <summary>
        /// 任务开始
        /// </summary>
        /// <param name="id"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void WaferTask_OnTaskStart(string id)
        {
            WaferInfo waferInfo = WaferManager.Instance.GetWaferByWaferId(id);
            if (waferInfo != null && waferInfo.WaferType == WaferType.Production)
            {
                ModuleName moduleName = (ModuleName)waferInfo.OriginStation;
                if (ModuleHelper.IsLoadPort(moduleName))
                {
                    CycleManager.Instance.UpdateCycleWaferCount(moduleName.ToString());
                }
                _schedulerFACallback.JobWaferStart(JobProcesser.Instance.GetControlJobInfoByProcessJob(waferInfo.ProcessJob),
                    waferInfo.SequenceName, waferInfo.OriginSlot);
            }
        }

        /// <summary>
        ///  Wafer task完成事件
        /// </summary>
        /// <param name="id"></param>
        private void WaferTask_OnTaskComplete(string id)
        {
            WaferInfo waferInfo=WaferManager.Instance.GetWaferByWaferId(id);
            if (waferInfo != null&&waferInfo.WaferType==WaferType.Production)
            {
                ModuleName moduleName = (ModuleName)waferInfo.OriginStation;
                if (ModuleHelper.IsLoadPort(moduleName))
                {
                    CycleManager.Instance.UpdateCycleWaferCount(moduleName.ToString());
                }
                _schedulerFACallback.JobWaferEnd(JobProcesser.Instance.GetControlJobInfoByProcessJob(waferInfo.ProcessJob), 
                    waferInfo.SequenceName, waferInfo.OriginSlot);
            }
            RemoveWaferTask(id);
        }
        /// <summary>
        /// 检验所有task是否完成
        /// </summary>
        /// <returns></returns>
        public bool CheckAllTaskComplete()
        {
            return _waferTaskList.Count == 0;
        }
        /// <summary>
        /// 暂停
        /// </summary>
        public void PauseAllTask()
        {
            List<WaferTask> waferTasks = _waferTaskList.ToList();
            foreach(WaferTask item in waferTasks)
            {
                item.Pause();
            }
        }
        /// <summary>
        /// 恢复所有任务
        /// </summary>
        public void ResumeAllTask()
        {
            List<WaferTask> waferTasks = _waferTaskList.ToList();
            foreach (WaferTask item in waferTasks)
            {
                item.Resume();
            }
        }
        /// <summary>
        /// 恢复所有任务
        /// </summary>
        public void RemoveAllTask()
        {
            List<WaferTask> waferTasks = _waferTaskList.ToList();
            foreach (WaferTask item in waferTasks)
            {
                RemoveWaferTask(item.WaferId);
            }
        }
        /// <summary>
        /// 根据WaferId获取配对另一个WaferId
        /// </summary>
        /// <param name="waferId"></param>
        /// <returns></returns>
        public string GetMatchWaferIdByWaferId(string waferId)
        {
            return _waferTaskMatchDic.ContainsKey(waferId) ? _waferTaskMatchDic[waferId] : "";
        }
        /// <summary>
        /// 移除WaferId匹配WaferHolderTask字典
        /// </summary>
        /// <param name="waferId"></param>
        public void RemoveWaferIdMatchWaferHolderTaskDic(string waferId)
        {
            if(_waferWaferHolderTaskDic.ContainsKey(waferId))
            {
                _waferWaferHolderTaskDic.TryRemove(waferId, out var waferHolderTask);
            }
        }
        /// <summary>
        /// 获取WaferId匹配WaferHolderTask字典
        /// </summary>
        /// <param name="waferId"></param>
        /// <returns></returns>
        public WaferHolderTask GetWaferHolderTaskByWaferId(string waferId)
        {
            return _waferWaferHolderTaskDic.ContainsKey(waferId) ? _waferWaferHolderTaskDic[waferId] : null;
        }
        /// <summary>
        /// 获取WaferHolder Task对应的Wafer Task WaferId集合
        /// </summary>
        /// <param name="waferHolderId"></param>
        /// <returns></returns>
        public List<string> GetWaferHolderMathWaferId(string waferHolderId)
        {
            List<string> keys = _waferWaferHolderTaskDic.Keys.ToList();
            List<string> result = new List<string>();
            foreach(string item in keys)
            {
                if(_waferWaferHolderTaskDic[item].WaferHolderInfo.Id==waferHolderId)
                {
                    result.Add(item);
                }
            }
            return result;
        }
        /// <summary>
        /// 检验Wafer存在匹配的wafer任务(wafer是单片任务还是双片任务)
        /// </summary>
        /// <param name="waferId"></param>
        /// <returns></returns>
        public string CheckWaferHasMatch(string waferId)
        {
            if (_waferTaskMatchDic.ContainsKey(waferId))
            {
                return _waferTaskMatchDic[waferId];
            }
            else
            {
                return "";
            }
        }
    }
}