using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using MECF.Framework.Common.DataCenter;
using MECF.Framework.Common.Equipment;
using RTDefine = Aitex.Core.Common;

namespace MECF.Framework.UI.Client.ClientBase
{
    public class ModuleDataMonitor
    {
        public Dictionary<string, ModuleInfo> _mapWaferDataModule = new Dictionary<string, ModuleInfo>();

        public List<string> _lstWaferDataName = new List<string>();

        private PeriodicJob _monitorThread;

        private bool isEFEMInstalled;

        public ModuleDataMonitor()
        {
            foreach (var moduleInfo in ModuleManager.ModuleInfos)
            {
                if (!string.IsNullOrEmpty(moduleInfo.Value.WaferDataName))
                {
                    _lstWaferDataName.Add(moduleInfo.Value.WaferDataName);
                    _mapWaferDataModule[moduleInfo.Value.WaferDataName] = moduleInfo.Value;
                }
            }
            isEFEMInstalled = (bool)QueryDataClient.Instance.Service.GetConfig($"System.SetUp.IsEFEMInstalled");

            _monitorThread = new PeriodicJob(500, OnTimer, "Monitor Module Data Thread", true);
        }

        private bool OnTimer()
        {
            try
            {
                Dictionary<string, object> data = QueryDataClient.Instance.Service.PollData(_lstWaferDataName);

                if (data != null && Application.Current != null)
                {
                    Application.Current.Dispatcher.Invoke(new Action(() =>
                    {
                        foreach (var waferData in data)
                        {
                            if (!_mapWaferDataModule.ContainsKey(waferData.Key))
                                continue;

                            RTDefine.WaferInfoRt[] wafers = waferData.Value as RTDefine.WaferInfoRt[];
                            if (wafers == null)
                                continue;

                            ModuleInfo info = _mapWaferDataModule[waferData.Key];
                            if (info.WaferManager.Wafers.Count == 0)
                            {
                                for (int i = 0; i < wafers.Length; i++)
                                {
                                    info.WaferManager.Wafers.Add(WaferInfoConverter(wafers[i], info.WaferModuleID, i));
                                }

                                if (info.IsWaferReverseDisplay)
                                {
                                    info.WaferManager.Wafers = new ObservableCollection<WaferInfo>(info.WaferManager.Wafers.Reverse());
                                }
                                continue;
                            }

                            if (wafers.Length == info.WaferManager.Wafers.Count)
                            {
                                int index;
                                
                                for (int i = 0; i < wafers.Length; i++)
                                {
                                    if (info.IsWaferReverseDisplay)
                                        index = wafers.Length - i - 1;
                                    else
                                        index = i;

                                    var convertedWafer = WaferInfoConverter(wafers[index], info.WaferModuleID, index);
                                    info.WaferManager.Wafers[i].WaferStatus = convertedWafer.WaferStatus;
                                    info.WaferManager.Wafers[i].WaferID = convertedWafer.WaferID;
                                    if (wafers[index].IsWaferEmpty)
                                    {
                                        info.WaferManager.Wafers[i].SourceName =wafers[index].TrayOriginStation+"."+ (wafers[index].TrayOriginSlot + 1).ToString().PadLeft(2,'0');
                                    }
                                    else
                                    {
                                        info.WaferManager.Wafers[i].SourceName = convertedWafer.SourceName;
                                    }
                                    info.WaferManager.Wafers[i].TrayStatus = convertedWafer.TrayStatus;
                                    info.WaferManager.Wafers[i].LotID = convertedWafer.LotID;
                                    info.WaferManager.Wafers[i].IsTrayExhausted = wafers[index].TrayProcessCount <= 0;
                                    info.WaferManager.Wafers[i].TrayProcessCount = wafers[index].TrayProcessCount;
                                    info.WaferManager.Wafers[i].RecipeName = convertedWafer.RecipeName;

                                    if (wafers[index].TrayOriginSlot % 2 == 0)
                                    {
                                        info.WaferManager.Wafers[i].TrayBelongTo = ModuleName.PM1.ToString();
                                    }
                                    else
                                    {
                                        info.WaferManager.Wafers[i].TrayBelongTo = ModuleName.PM2.ToString();
                                    }
                                    
                                    if (!isEFEMInstalled)
                                    {
                                        info.WaferManager.Wafers[i].TrayBelongTo = wafers[index].TrayBelongTo;
                                    }
                                    
                                    if (info.WaferManager.Wafers[i].ToolTip == null)
                                    {
                                        info.WaferManager.Wafers[i].ToolTip = new ToolTip()
                                        {
                                            Content = $"LotId : {wafers[index].LotId}\r\nWaferId : {wafers[index].WaferID}\r\nSequenceName : {wafers[index].ProcessJobID}\r\nRecipeName : {convertedWafer.RecipeName}\r\nWaferStatus : {((int)wafers[index].WaferStatus).ToString()}\r\nNextSequenceStep : {wafers[index].NextSequenceStep + 1}\r\nTrayState : {((int)wafers[index].TrayStatus).ToString()}\r\nTrayProcessCount : {wafers[index].TrayProcessCount}\r\nTrayOriginStation : {wafers[index].TrayOriginStation}\r\nTrayOriginSlot : {wafers[index].TrayOriginSlot + 1}\r\nTrayBelongTo : {info.WaferManager.Wafers[i].TrayBelongTo}"
                                        };
                                    }
                                    else
                                    {
                                        info.WaferManager.Wafers[i].ToolTip.Content = $"LotId : {wafers[index].LotId}\r\nWaferId : {wafers[index].WaferID}\r\nSequenceName : {wafers[index].ProcessJobID}\r\nRecipeName : {convertedWafer.RecipeName}\r\nWaferStatus : {((int)wafers[index].WaferStatus).ToString()}\r\nNextSequenceStep : {wafers[index].NextSequenceStep + 1}\r\nTrayState : {((int)wafers[index].TrayStatus).ToString()}\r\nTrayProcessCount : {wafers[index].TrayProcessCount}\r\nTrayOriginStation : {wafers[index].TrayOriginStation}\r\nTrayOriginSlot : {wafers[index].TrayOriginSlot + 1}\r\nTrayBelongTo : {info.WaferManager.Wafers[i].TrayBelongTo}";
                                    }

                                }
                            }
                        }
                    }));
                }
            }
            catch (Exception ex)
            {
                LOG.Error(ex.Message);
            }

            return true;
        }


        private WaferInfo WaferInfoConverter(RTDefine.WaferInfoRt awafer, string modid, int slotid)
        {
            WaferInfo wafer = new WaferInfo();
            wafer.ModuleID = modid;
            wafer.SlotID = slotid;
            wafer.SlotIndex = slotid + 1;
            wafer.WaferID = awafer.WaferID;
            wafer.SourceName = awafer.WaferOrigin;
            wafer.LotID = awafer.LotId == "" ? awafer.WaferOrigin : awafer.LotId;
            wafer.WaferStatus = WaferStatusConverter(awafer);
            wafer.TrayStatus = (int)awafer.TrayStatus; //awafer.TrayState == RTDefine.TrayStatus.Normal ? 1 : 0;
            wafer.RecipeName = "";
            if (awafer.ProcessJob != null && awafer.ProcessJob.Sequence != null)
            {
                for (int i = 0; i < awafer.ProcessJob.Sequence.Steps.Count; i++)
                {
                    if (!String.IsNullOrEmpty(awafer.ProcessJob.Sequence.Steps[i].RecipeName))
                    {
                        wafer.RecipeName = awafer.ProcessJob.Sequence.Steps[i].RecipeName;
                        wafer.SequenceName = awafer.ProcessJob.Sequence.Name;
                        break;
                    }
                }
            }
            return wafer;
        }

        //0: no wafer
        //1:light blue  == idle no pj
        //2:blue    = idle with pj
        //3:cyan      = in process
        //4:green = complete
        //5:error  = error
        //6:dummy   
        //7:warning  = has error
        //8:partial processed
        private int WaferStatusConverter(RTDefine.WaferInfoRt awafer)
        {
            if (awafer.WaferStatus == RTDefine.WaferStatus.Empty)
                return 0;

            if (awafer.WaferStatus == RTDefine.WaferStatus.Normal)
            {
                switch (awafer.ProcessState)
                {
                    case RTDefine.WaferProcessStatus.InProcess: return 3;
                    case RTDefine.WaferProcessStatus.Completed: return awafer.HasWarning ? 7 : 4;
                    case RTDefine.WaferProcessStatus.Failed: return 5;
                    case RTDefine.WaferProcessStatus.Wait: return 3;
                    case RTDefine.WaferProcessStatus.Idle: return awafer.ProcessJob == null ? 1 : 2;
                }
            }

            if (awafer.WaferStatus == RTDefine.WaferStatus.Dummy)
            {
                return 6;
            }

            return 5;
        }

    }

}
