using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Threading;

namespace AxCopilot.Services;

public class FileDialogWatcher : IDisposable
{
	private delegate void WinEventDelegate(nint hWinEventHook, uint eventType, nint hwnd, int idObject, int idChild, uint idEventThread, uint dwmsEventTime);

	private const uint EVENT_OBJECT_SHOW = 32770u;

	private const uint EVENT_OBJECT_CREATE = 32768u;

	private const uint WINEVENT_OUTOFCONTEXT = 0u;

	private const uint WINEVENT_SKIPOWNPROCESS = 2u;

	private nint _hook;

	private WinEventDelegate? _delegate;

	private bool _disposed;

	private readonly Dispatcher _dispatcher;

	public event EventHandler<nint>? FileDialogOpened;

	[DllImport("user32.dll")]
	private static extern nint SetWinEventHook(uint eventMin, uint eventMax, nint hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);

	[DllImport("user32.dll")]
	private static extern bool UnhookWinEvent(nint hWinEventHook);

	[DllImport("user32.dll", CharSet = CharSet.Unicode)]
	private static extern int GetClassName(nint hWnd, StringBuilder lpClassName, int nMaxCount);

	[DllImport("user32.dll", CharSet = CharSet.Unicode)]
	private static extern int GetWindowText(nint hWnd, StringBuilder lpString, int nMaxCount);

	[DllImport("user32.dll")]
	private static extern bool IsWindowVisible(nint hWnd);

	public FileDialogWatcher()
	{
		_dispatcher = Dispatcher.CurrentDispatcher;
	}

	public void Start()
	{
		if (_hook == IntPtr.Zero)
		{
			_delegate = OnWinEvent;
			_hook = SetWinEventHook(32770u, 32770u, IntPtr.Zero, _delegate, 0u, 0u, 2u);
		}
	}

	public void Stop()
	{
		if (_hook != IntPtr.Zero)
		{
			UnhookWinEvent(_hook);
			_hook = IntPtr.Zero;
		}
	}

	private void OnWinEvent(nint hWinEventHook, uint eventType, nint hwnd, int idObject, int idChild, uint idEventThread, uint dwmsEventTime)
	{
		if (hwnd == IntPtr.Zero || idObject != 0 || !IsWindowVisible(hwnd))
		{
			return;
		}
		StringBuilder stringBuilder = new StringBuilder(256);
		GetClassName(hwnd, stringBuilder, 256);
		string text = stringBuilder.ToString();
		if (text != "#32770")
		{
			return;
		}
		StringBuilder stringBuilder2 = new StringBuilder(256);
		GetWindowText(hwnd, stringBuilder2, 256);
		string text2 = stringBuilder2.ToString();
		if (text2.Contains("열기") || text2.Contains("Open") || text2.Contains("저장") || text2.Contains("Save") || text2.Contains("다른 이름") || text2.Contains("Browse") || text2.Contains("폴더") || text2.Contains("Folder"))
		{
			_dispatcher.BeginInvoke((Delegate)(Action)delegate
			{
				this.FileDialogOpened?.Invoke(this, hwnd);
			}, Array.Empty<object>());
		}
	}

	public void Dispose()
	{
		if (!_disposed)
		{
			_disposed = true;
			Stop();
		}
	}
}
