using Aitex.Core.RT.Device.Unit;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.SCCore;
using MECF.Framework.Common.Equipment;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Management;
using System.Reflection;
using System.ServiceModel.Channels;
using System.Text;
using System.Timers;
using System.Windows;

namespace Venus_RT.Modules
{
    public class ResourceMonitor
    {
        private string processRTname = Process.GetCurrentProcess().ProcessName;
        private string processUIname = "Venus_UI";
        private string processSimuname = "Venus_Simulator";
        //private int _stringlen = 20;
        private int threshold = 800;
        private Process pro;
        private Timer _timer;
        //数据波动监测可用
        //List<double> _Numberofhandlesopened = new List<double>() { };
        //List<double> _Numberofmodules = new List<double>() { };
        //List<double> _Basicpriority = new List<double>() { };
        //List<double> _processor = new List<double>() { };
        //List<double> _Minimumworkingset = new List<double>() { };
        //List<double> _MaximumWorkingSet = new List<double>() { };
        //List<double> _Workset = new List<double>() { };
        //List<double> _Peakworkingset = new List<double>() { };
        //List<double> _Dedicatedmemorysize = new List<double>() { };
        //List<double> _UnpagedMemorySize = new List<double>() { };
        //List<double> _PagingMemorySize = new List<double>() { };
        //List<double> _Peakpagingmemorysize = new List<double>() { };
        //List<double> _VirtualMemorySize = new List<double>() { };
        //List<double> _PeakVirtualMemorySize = new List<double>() { };

        //string ProcessName              = string.Empty;
        //string ProcessID                = string.Empty;
        //string Starttime                = string.Empty;
        private string Response                 = string.Empty;
        private string MainWindowHandle         = string.Empty;
        //string MainWindowTitle          = string.Empty;
        private string AssociatedProcessHandle  = string.Empty;
        private string Numberofhandlesopened    = string.Empty;
        private string Numberofmodules          = string.Empty;
        private string Basicpriority            = string.Empty;
        private string Increasepriority         = string.Empty;
        private string processor                = string.Empty;
        private string Minimumworkingset        = string.Empty;
        private string MaximumWorkingSet        = string.Empty;
        private string Workset                  = string.Empty;
        private string Peakworkingset           = string.Empty;
        private string Dedicatedmemorysize      = string.Empty;
        private string UnpagedMemorySize        = string.Empty;
        private string PagingMemorySize         = string.Empty;
        private string Peakpagingmemorysize     = string.Empty;
        private string VirtualMemorySize        = string.Empty;
        private string PeakVirtualMemorySize    = string.Empty;
        private string Occupytime               = string.Empty;
        private string PrivilegeOccupancytime   = string.Empty;
        private string Useroccupiedtime         = string.Empty;
        private PerformanceCounter CpuOccupied;
        public ResourceMonitor() 
        {

            //ProcessName = "进程名称";
            //ProcessID = "进程ID".PadRight(_stringlen - 2, ' ');
            //Starttime = "启动时间";
            Response = "Response or not";
            MainWindowHandle = "Main Window Handle";
            //MainWindowTitle = "主窗口标题";
            AssociatedProcessHandle = "Associated Process Handle ";
            Numberofhandlesopened = "Number of handles opened ";
            Numberofmodules = "Number of modules ";
            Basicpriority = "Basic priority ";
            Increasepriority = "Increase priority ";
            processor = "processor ";
            Minimumworkingset = "Minimum working set ";
            MaximumWorkingSet = "Maximum working Set ";
            Workset = "Work set ";
            Peakworkingset = "Peak working set ";
            Dedicatedmemorysize = "Dedicated memory size ";
            UnpagedMemorySize = "Unpaged Memory Size ";
            PagingMemorySize = "Paging Memory Size ";
            Peakpagingmemorysize = "Peak paging memory size ";
            VirtualMemorySize = "Virtual Memory Size ";
            PeakVirtualMemorySize = "Peak Virtual Memory Size ";
            Occupytime = "Occupy time ";
            PrivilegeOccupancytime = "Privilege Occupancy time ";
            Useroccupiedtime = "User occupied time ";
            
        }

        ~ResourceMonitor() => _timer.Dispose();//定时器销毁

        public bool Initialize()
        {
            //>0 开启否则不开启
            if (SC.GetValue<int>("System.CheckResourceInterval") > 0)
            {
                _timer = new Timer();
                CpuOccupied  = new PerformanceCounter("Processor", "% Processor Time", "_Total");
                _timer.Enabled = true;
                _timer.Interval = SC.GetValue<int>("System.CheckResourceInterval") * 60 * 1000;
                _timer.Elapsed += GetProcessInfo;
                _timer.Start();
                //LOG.Write($"{ProcessName}" +
                //$"{ProcessID}" +
                ////$"{Starttime}"+
                //$"{Response}" +
                //$"{MainWindowHandle}" +
                ////$"{MainWindowTitle}"+
                //$"{AssociatedProcessHandle}" +
                //$"{Numberofhandlesopened}" +
                //$"{Numberofmodules}" +
                //$"{Basicpriority}" +
                //$"{Increasepriority}" +
                //$"{processor}" +
                //$"{Minimumworkingset}" +
                //$"{MaximumWorkingSet}" +
                //$"{Workset}" +
                //$"{Peakworkingset}" +
                //$"{Dedicatedmemorysize}" +
                //$"{UnpagedMemorySize}" +
                //$"{PagingMemorySize}" +
                //$"{Peakpagingmemorysize}" +
                //$"{VirtualMemorySize}" +
                //$"{PeakVirtualMemorySize}" +
                //$"{Occupytime}" +
                //$"{PrivilegeOccupancytime}" +
                //$"{Useroccupiedtime}");
            }
            return true;
        }

        private void GetProcessInfo(object sender, ElapsedEventArgs e)
        {
            try
            {
                string rtmonoitor = process_use(processRTname);
                string uimonoitor = process_use(processUIname); 
                string simumonoitor = process_use(processSimuname); 

                string systemMonitor = $"PC => {drive_use()}" +
                    $"{cpu_use()}" +
                    $"{memory_use()}";

                LOG.Write(eEvent.INFO_WINRESOURCE, ModuleName.System,
                    rtmonoitor +
                    " ".PadLeft(56, ' ') + uimonoitor +
                    " ".PadLeft(56, ' ') + simumonoitor +
                    " ".PadLeft(56, ' ') + systemMonitor 
                );
                //没有就不做任何操作

            }
            catch (Exception ex)
            {
                LOG.Write(eEvent.ERR_WINRESOURCE, ModuleName.System,$"Monitor Error happened: {ex}");
            }
        }

        //process
        private string process_use(string processname)
        {
            string monitor = "";
            //判断是否存在该进程
            //有就开始记录
            if (Process.GetProcessesByName(processname).Length > 0)
            {
                pro = Process.GetProcessesByName(processname)[0];

                //_Numberofhandlesopened.Add(pro.HandleCount);         //进程打开的句柄数
                //_Numberofmodules.Add(pro.Modules.Count);               //模块数量
                //_Basicpriority.Add(pro.BasePriority);                 //基本优先级
                //_processor.Add(pro.ProcessorAffinity.ToInt32());                     //处理器
                //_Minimumworkingset.Add(pro.MinWorkingSet.ToInt32());             //最小工作集
                //_MaximumWorkingSet.Add(pro.MaxWorkingSet.ToInt32());             //最大工作集
                //_Workset.Add(Convert.ToInt32(pro.WorkingSet64));                       //工作集
                //_Peakworkingset.Add(Convert.ToInt32(pro.PeakWorkingSet64));                //峰值工作集
                //_Dedicatedmemorysize.Add(Convert.ToInt32(pro.PrivateMemorySize64 / 1048576));           //专用内存大小
                //_UnpagedMemorySize.Add(Convert.ToInt32(pro.NonpagedSystemMemorySize64 / 1048576));             //未分页内存大小
                //_PagingMemorySize.Add(Convert.ToInt32(pro.PagedMemorySize64 / 1048576));              //分页内存大小
                //_Peakpagingmemorysize.Add(Convert.ToInt32(pro.PeakPagedMemorySize64 / 1048576));          //峰值分页内存大小
                //_VirtualMemorySize.Add(Convert.ToInt32(pro.VirtualMemorySize64 / 1024));             //虚拟内存大小
                //_PeakVirtualMemorySize.Add(Convert.ToInt32(pro.PeakVirtualMemorySize64 / 1048576));         //峰值虚拟内存大小

                monitor = //$"{ProcessName}:{pro.ProcessName}" +
                                   //$"{pro.StartTime.ToLongDateString() + pro.StartTime.ToLongTimeString()}" +
                $"{processname} => {Response}:{pro.Responding.ToString()}\t" +
                $"{MainWindowHandle}:{pro.MainWindowHandle.ToString()}\t" +
                //$"{pro.MainWindowTitle}" +
                $"{AssociatedProcessHandle}:{pro.Handle.ToString()}\t" +
                $"{Numberofhandlesopened}:{pro.HandleCount.ToString()}\t" +
                $"{Numberofmodules}:{pro.Modules.Count.ToString()}\t" +
                $"{Basicpriority}:{pro.BasePriority.ToString()} \t" +
                $"{Increasepriority}:{pro.PriorityBoostEnabled.ToString()}\t" +
                $"{processor}:{pro.ProcessorAffinity.ToInt32().ToString()}\t" +
                //$"{Minimumworkingset}:{pro.MinWorkingSet.ToInt32().ToString()}\t" +
                $"{MaximumWorkingSet}:{pro.MaxWorkingSet.ToInt32().ToString()}\t" +
                $"{Workset}:{pro.WorkingSet64.ToString()}\t" +
                $"{Peakworkingset}:{pro.PeakWorkingSet64.ToString()}\t" +
                $"{Dedicatedmemorysize}:{(pro.PrivateMemorySize64 / 1048576).ToString()}MB\t" +
                $"{UnpagedMemorySize}:{(pro.NonpagedSystemMemorySize64 / 1048576).ToString()}MB\t" +
                $"{PagingMemorySize}:{(pro.PagedMemorySize64 / 1048576).ToString()}MB\t" +
                $"{Peakpagingmemorysize}:{(pro.PeakPagedMemorySize64 / 1048576).ToString()}MB\t" +
                $"{VirtualMemorySize}:{(pro.VirtualMemorySize64 / 1048576).ToString()}MB\t" +
                $"{PeakVirtualMemorySize}:{(pro.PeakVirtualMemorySize64 / 1048576).ToString()}MB\t" +
                $"{Occupytime}:{pro.TotalProcessorTime.ToString()}\t" +
                $"{PrivilegeOccupancytime}:{pro.PrivilegedProcessorTime.ToString()}\t" +
                $"{Useroccupiedtime}:{pro.UserProcessorTime.ToString()}\r\n";

                //如果虚拟内存大于800MB 即报警
                if (pro.PagedMemorySize64 / 1048576 >= threshold)
                {
                    LOG.Write(eEvent.WARN_WINRESOURCE, ModuleName.System, $"警告!进程 {processname} 内存异常增长,超过{threshold}MB阈值!");
                }
            }
            return monitor;
        }

        //CPU
        private string cpu_use()
        {

            float cpu_use_per = CpuOccupied.NextValue();
            string cpu_use = $"CPU usage rate:{cpu_use_per:F2}%\t";
            return cpu_use;
        }
        
        //disk
        private string drive_use()
        {
            string drive_use = "";
            foreach (DriveInfo drive in DriveInfo.GetDrives())
            {
                if (drive.IsReady)
                {
                    drive_use += $"{drive.Name}";
                    drive_use += $" Total:{drive.TotalSize / 1024 / 1024 }MB";
                    drive_use += $" Used:{(drive.TotalSize - drive.AvailableFreeSpace) / 1024 / 1024 }MB";
                    drive_use += $" Free:{drive.AvailableFreeSpace / 1024 / 1024 }MB\t";
                }
            }
            return drive_use;
        }
        //memory
        private string memory_use()
        {
            string memory_use = "Memory status:" +
                $"Memory Available:{GetMemoryAvailable():F2}GB\t" +
                $"Memory Used:{GetMemoryUsed():F2}GB\t" +
                $"Memory Used Rate:{GetMemoryUsedRate():F2}%\t";
            return memory_use;
        }

        //MemoryAvailable
        private double? GetMemoryAvailable()
        {

            double availablebytes = 0;
            var managementClassOs = new ManagementClass("Win32_OperatingSystem");
            foreach (var managementBaseObject in managementClassOs.GetInstances())
                if (managementBaseObject["FreePhysicalMemory"] != null)
                    availablebytes = 1024 * double.Parse(managementBaseObject["FreePhysicalMemory"].ToString());
            return availablebytes / GbDiv;

        }
        //MemoryUsed
        private double? GetMemoryUsed()
        {
            double? PhysicalMemory = GetPhysicalMemory();
            double? MemoryAvailable = GetMemoryAvailable();
            double? MemoryUsed = (double?)(PhysicalMemory - MemoryAvailable);
            double currentMemoryUsed = (double)MemoryUsed;
            return currentMemoryUsed;
        }
        //PhysicalMemory
        private long? GetPhysicalMemory()
        {
            //获得物理内存
            var managementClass = new ManagementClass("Win32_ComputerSystem");
            var managementObjectCollection = managementClass.GetInstances();
            //long PhysicalMemory;
            foreach (var managementBaseObject in managementObjectCollection)
                if (managementBaseObject["TotalPhysicalMemory"] != null)
                {
                    return long.Parse(managementBaseObject["TotalPhysicalMemory"].ToString()) / GbDiv;
                }
            return null;

        }
        //MemoryUsedRate
        private double? GetMemoryUsedRate()
        {
            double? PhysicalMemory = GetPhysicalMemory();
            double? MemoryAvailable = GetMemoryAvailable();
            double? MemoryUsedRate = (double?)(PhysicalMemory - MemoryAvailable) / PhysicalMemory;
            return MemoryUsedRate.HasValue ? Convert.ToDouble(MemoryUsedRate * 100) : 0;
        }

        
        #region 单位转换进制

        private const int KbDiv = 1024;
        private const int MbDiv = 1024 * 1024;
        private const int GbDiv = 1024 * 1024 * 1024;

        #endregion
    }
}