using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Threading;
using Microsoft.Win32;

namespace AxCopilot.Views;

public class ResourceMonitorWindow : Window, IComponentConnector
{
	[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
	private struct MEMORYSTATUSEX
	{
		public uint dwLength;

		public uint dwMemoryLoad;

		public ulong ullTotalPhys;

		public ulong ullAvailPhys;

		public ulong ullTotalPageFile;

		public ulong ullAvailPageFile;

		public ulong ullTotalVirtual;

		public ulong ullAvailVirtual;

		public ulong ullAvailExtendedVirtual;
	}

	public sealed class DriveDisplayItem : INotifyPropertyChanged
	{
		private string _label = "";

		private string _detail = "";

		private double _barWidth = 0.0;

		private Brush _barColor = Brushes.Green;

		public string Label
		{
			get
			{
				return _label;
			}
			set
			{
				_label = value;
				OnPropertyChanged("Label");
			}
		}

		public string Detail
		{
			get
			{
				return _detail;
			}
			set
			{
				_detail = value;
				OnPropertyChanged("Detail");
			}
		}

		public double BarWidth
		{
			get
			{
				return _barWidth;
			}
			set
			{
				_barWidth = value;
				OnPropertyChanged("BarWidth");
			}
		}

		public Brush BarColor
		{
			get
			{
				return _barColor;
			}
			set
			{
				_barColor = value;
				OnPropertyChanged("BarColor");
			}
		}

		public ICommand OpenCommand { get; init; } = null;

		public event PropertyChangedEventHandler? PropertyChanged;

		private void OnPropertyChanged([CallerMemberName] string? n = null)
		{
			this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(n));
		}
	}

	public sealed class ProcessDisplayItem
	{
		public string Rank { get; init; } = "";

		public string Name { get; init; } = "";

		public string MemText { get; init; } = "";

		public double BarWidth { get; init; }
	}

	private sealed class RelayCommand(Action execute) : ICommand
	{
		public event EventHandler? CanExecuteChanged
		{
			add
			{
			}
			remove
			{
			}
		}

		public bool CanExecute(object? _)
		{
			return true;
		}

		public void Execute(object? _)
		{
			execute();
		}
	}

	private const int WM_NCLBUTTONDOWN = 161;

	private const int HTBOTTOMRIGHT = 17;

	private readonly DispatcherTimer _timer;

	private static PerformanceCounter? _cpuCounter;

	private static float _cpuCached;

	private static DateTime _cpuUpdated = DateTime.MinValue;

	private readonly ObservableCollection<DriveDisplayItem> _drives = new ObservableCollection<DriveDisplayItem>();

	private const double MaxBarWidth = 160.0;

	internal TextBlock RefreshLabel;

	internal TextBlock CpuValueText;

	internal Border CpuBar;

	internal TextBlock CpuNameText;

	internal TextBlock RamValueText;

	internal Border RamBar;

	internal TextBlock RamDetailText;

	internal ItemsControl DriveList;

	internal ItemsControl ProcessList;

	internal TextBlock UptimeText;

	private bool _contentLoaded;

	[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
	[return: MarshalAs(UnmanagedType.Bool)]
	private static extern bool GlobalMemoryStatusEx(ref MEMORYSTATUSEX lpBuffer);

	[DllImport("user32.dll")]
	private static extern void ReleaseCapture();

	[DllImport("user32.dll")]
	private static extern nint SendMessage(nint hWnd, int msg, nint wParam, nint lParam);

	public ResourceMonitorWindow()
	{
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Expected O, but got Unknown
		InitializeComponent();
		DriveList.ItemsSource = _drives;
		if (_cpuCounter == null)
		{
			try
			{
				_cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");
				_cpuCounter.NextValue();
			}
			catch
			{
			}
		}
		InitDrives();
		_timer = new DispatcherTimer
		{
			Interval = TimeSpan.FromSeconds(1.0)
		};
		_timer.Tick += delegate
		{
			Refresh();
		};
		_timer.Start();
		Refresh();
	}

	private void InitDrives()
	{
		_drives.Clear();
		foreach (DriveInfo item in from d in DriveInfo.GetDrives()
			where d.IsReady && d.DriveType == DriveType.Fixed
			select d)
		{
			string root = item.RootDirectory.FullName;
			_drives.Add(new DriveDisplayItem
			{
				OpenCommand = new RelayCommand(delegate
				{
					try
					{
						Process.Start(new ProcessStartInfo("explorer.exe", root)
						{
							UseShellExecute = true
						});
					}
					catch
					{
					}
				})
			});
		}
	}

	private void Refresh()
	{
		RefreshCpu();
		RefreshRam();
		RefreshDrives();
		RefreshProcesses();
		RefreshUptime();
	}

	private void RefreshCpu()
	{
		try
		{
			if (_cpuCounter == null)
			{
				CpuValueText.Text = "—";
				return;
			}
			if ((DateTime.Now - _cpuUpdated).TotalMilliseconds > 800.0)
			{
				_cpuCached = _cpuCounter.NextValue();
				_cpuUpdated = DateTime.Now;
			}
			int num = (int)Math.Clamp(_cpuCached, 0f, 100f);
			CpuValueText.Text = $"{num}%";
			SolidColorBrush solidColorBrush = ((num > 80) ? new SolidColorBrush(Color.FromRgb(220, 38, 38)) : ((num > 50) ? new SolidColorBrush(Color.FromRgb(217, 119, 6)) : new SolidColorBrush(Color.FromRgb(75, 158, 252))));
			CpuValueText.Foreground = solidColorBrush;
			CpuBar.Background = solidColorBrush;
			Border cpuBar = CpuBar;
			FrameworkElement obj = CpuBar.Parent as FrameworkElement;
			cpuBar.Width = ((obj != null) ? (obj.ActualWidth * (double)num / 100.0) : 0.0);
			if (string.IsNullOrEmpty(CpuNameText.Text))
			{
				CpuNameText.Text = GetProcessorName();
			}
		}
		catch
		{
			CpuValueText.Text = "—";
		}
	}

	private void RefreshRam()
	{
		MEMORYSTATUSEX lpBuffer = new MEMORYSTATUSEX
		{
			dwLength = (uint)Marshal.SizeOf<MEMORYSTATUSEX>()
		};
		if (GlobalMemoryStatusEx(ref lpBuffer))
		{
			double value = (double)lpBuffer.ullTotalPhys / 1024.0 / 1024.0 / 1024.0;
			double value2 = (double)(lpBuffer.ullTotalPhys - lpBuffer.ullAvailPhys) / 1024.0 / 1024.0 / 1024.0;
			double value3 = (double)lpBuffer.ullAvailPhys / 1024.0 / 1024.0 / 1024.0;
			int dwMemoryLoad = (int)lpBuffer.dwMemoryLoad;
			RamValueText.Text = $"{dwMemoryLoad}%";
			RamDetailText.Text = $"사용: {value2:F1} GB  /  전체: {value:F1} GB  /  여유: {value3:F1} GB";
			Border ramBar = RamBar;
			FrameworkElement obj = RamBar.Parent as FrameworkElement;
			ramBar.Width = ((obj != null) ? (obj.ActualWidth * (double)dwMemoryLoad / 100.0) : 0.0);
			SolidColorBrush solidColorBrush = ((dwMemoryLoad > 85) ? new SolidColorBrush(Color.FromRgb(220, 38, 38)) : ((dwMemoryLoad > 65) ? new SolidColorBrush(Color.FromRgb(217, 119, 6)) : new SolidColorBrush(Color.FromRgb(124, 58, 237))));
			RamValueText.Foreground = solidColorBrush;
			RamBar.Background = solidColorBrush;
		}
	}

	private void RefreshDrives()
	{
		List<DriveInfo> list = (from d in DriveInfo.GetDrives()
			where d.IsReady && d.DriveType == DriveType.Fixed
			select d).ToList();
		if (list.Count != _drives.Count)
		{
			InitDrives();
		}
		for (int num = 0; num < list.Count && num < _drives.Count; num++)
		{
			DriveInfo driveInfo = list[num];
			double num2 = (double)driveInfo.TotalSize / 1024.0 / 1024.0 / 1024.0;
			double num3 = (double)driveInfo.AvailableFreeSpace / 1024.0 / 1024.0 / 1024.0;
			double num4 = num2 - num3;
			int num5 = (int)(num4 / num2 * 100.0);
			string label = (string.IsNullOrWhiteSpace(driveInfo.VolumeLabel) ? driveInfo.Name.TrimEnd('\\') : (driveInfo.Name.TrimEnd('\\') + " (" + driveInfo.VolumeLabel + ")"));
			_drives[num].Label = label;
			_drives[num].Detail = $"{num3:F1}GB 여유";
			_drives[num].BarWidth = 160.0 * (double)num5 / 100.0;
			_drives[num].BarColor = ((num5 > 90) ? new SolidColorBrush(Color.FromRgb(220, 38, 38)) : ((num5 > 75) ? new SolidColorBrush(Color.FromRgb(217, 119, 6)) : new SolidColorBrush(Color.FromRgb(5, 150, 105))));
		}
	}

	private void RefreshProcesses()
	{
		try
		{
			List<Process> list = Process.GetProcesses().OrderByDescending(delegate(Process p)
			{
				try
				{
					return p.WorkingSet64;
				}
				catch
				{
					return 0L;
				}
			}).Take(7)
				.ToList();
			long maxMem = ((list.Count <= 0) ? 1 : ((list[0].WorkingSet64 > 0) ? list[0].WorkingSet64 : 1));
			List<ProcessDisplayItem> itemsSource = list.Select(delegate(Process p, int i)
			{
				long num = 0L;
				string text = "";
				try
				{
					num = p.WorkingSet64;
					text = p.ProcessName;
				}
				catch
				{
					text = "—";
				}
				double num2 = (double)num / 1024.0 / 1024.0;
				return new ProcessDisplayItem
				{
					Rank = $"{i + 1}",
					Name = text,
					MemText = ((num2 > 1024.0) ? $"{num2 / 1024.0:F1} GB" : $"{num2:F0} MB"),
					BarWidth = Math.Max(2.0, 46.0 * (double)num / (double)maxMem)
				};
			}).ToList();
			ProcessList.ItemsSource = itemsSource;
		}
		catch
		{
		}
	}

	private void RefreshUptime()
	{
		TimeSpan timeSpan = TimeSpan.FromMilliseconds(Environment.TickCount64);
		int num = (int)timeSpan.TotalDays;
		int hours = timeSpan.Hours;
		int minutes = timeSpan.Minutes;
		UptimeText.Text = ((num > 0) ? $"가동: {num}일 {hours}시간 {minutes}분" : ((hours > 0) ? $"가동: {hours}시간 {minutes}분" : $"가동: {minutes}분 {timeSpan.Seconds}초"));
	}

	private void ResizeGrip_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
	{
		if (e.ButtonState == MouseButtonState.Pressed)
		{
			ReleaseCapture();
			SendMessage(new WindowInteropHelper(this).Handle, 161, 17, IntPtr.Zero);
		}
	}

	private void Close_Click(object sender, RoutedEventArgs e)
	{
		Close();
	}

	private void Window_KeyDown(object sender, KeyEventArgs e)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Invalid comparison between Unknown and I4
		if ((int)e.Key == 13)
		{
			Close();
		}
	}

	private void Window_MouseDown(object sender, MouseButtonEventArgs e)
	{
		if (e.ChangedButton == MouseButton.Left && e.LeftButton == MouseButtonState.Pressed)
		{
			try
			{
				DragMove();
			}
			catch
			{
			}
		}
	}

	protected override void OnMouseWheel(MouseWheelEventArgs e)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Invalid comparison between Unknown and I4
		if ((int)Keyboard.Modifiers == 2)
		{
			int num = ((e.Delta > 0) ? 40 : (-40));
			double num2 = base.Height + (double)num;
			if (num2 >= base.MinHeight && num2 <= 900.0)
			{
				base.Height = num2;
			}
			e.Handled = true;
		}
		else
		{
			base.OnMouseWheel(e);
		}
	}

	protected override void OnClosed(EventArgs e)
	{
		_timer.Stop();
		base.OnClosed(e);
	}

	private static string GetProcessorName()
	{
		try
		{
			using RegistryKey registryKey = Registry.LocalMachine.OpenSubKey("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0");
			return (registryKey?.GetValue("ProcessorNameString") as string) ?? "";
		}
		catch
		{
			return "";
		}
	}

	[DebuggerNonUserCode]
	[GeneratedCode("PresentationBuildTasks", "10.0.5.0")]
	public void InitializeComponent()
	{
		if (!_contentLoaded)
		{
			_contentLoaded = true;
			Uri resourceLocator = new Uri("/AxCopilot;component/views/resourcemonitorwindow.xaml", UriKind.Relative);
			Application.LoadComponent(this, resourceLocator);
		}
	}

	[DebuggerNonUserCode]
	[GeneratedCode("PresentationBuildTasks", "10.0.5.0")]
	[EditorBrowsable(EditorBrowsableState.Never)]
	void IComponentConnector.Connect(int connectionId, object target)
	{
		switch (connectionId)
		{
		case 1:
			((ResourceMonitorWindow)target).MouseDown += Window_MouseDown;
			((ResourceMonitorWindow)target).KeyDown += Window_KeyDown;
			break;
		case 2:
			RefreshLabel = (TextBlock)target;
			break;
		case 3:
			((Button)target).Click += Close_Click;
			break;
		case 4:
			CpuValueText = (TextBlock)target;
			break;
		case 5:
			CpuBar = (Border)target;
			break;
		case 6:
			CpuNameText = (TextBlock)target;
			break;
		case 7:
			RamValueText = (TextBlock)target;
			break;
		case 8:
			RamBar = (Border)target;
			break;
		case 9:
			RamDetailText = (TextBlock)target;
			break;
		case 10:
			DriveList = (ItemsControl)target;
			break;
		case 11:
			ProcessList = (ItemsControl)target;
			break;
		case 12:
			((Border)target).MouseLeftButtonDown += ResizeGrip_MouseLeftButtonDown;
			break;
		case 13:
			UptimeText = (TextBlock)target;
			break;
		case 14:
			((Button)target).Click += Close_Click;
			break;
		default:
			_contentLoaded = true;
			break;
		}
	}
}
