using System;
using System.Runtime.InteropServices;
using Cute;
using UnityEngine;

public class WindowResize
{
	public delegate IntPtr WndProcDelegate(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);

	public struct Rect
	{
		public int Left { get; set; }

		public int Top { get; set; }

		public int Right { get; set; }

		public int Bottom { get; set; }

		public int Width
		{
			get
			{
				return Right - Left;
			}
			set
			{
				Right = Left + value;
			}
		}

		public int Height
		{
			get
			{
				return Bottom - Top;
			}
			set
			{
				Bottom = Top + value;
			}
		}

		public Rect(int left, int top, int right, int bottom)
		{
			this = default(Rect);
			Left = left;
			Top = top;
			Right = right;
			Bottom = bottom;
		}
	}

	public struct WindowPos
	{
		public IntPtr hwnd;

		public IntPtr hwndafter;

		public int x;

		public int y;

		public int cx;

		public int cy;

		public uint flags;
	}

	private const int WINDOW_WIDTH_MIN = 128;

	private const int WINDOW_HEIGHT_MIN = 59;

	public const float ASPECT_RATIO_MAX = 2.1666667f;

	public const float ASPECT_RATIO_MIN = 1.333f;

	private static int _windowLastWidth;

	private static int _windowLastHeight;

	private static bool _lastFullscreen;

	private static int? _requestUiUpdateFrame;

	private static int _frameLastWidth;

	private static int _frameLastHeight;

	private const int WM_WINDOWPOSCHANGING = 70;

	private const int WM_SIZING = 532;

	private const int WMSZ_LEFT = 1;

	private const int WMSZ_TOP = 3;

	private const int WMSZ_TOPLEFT = 4;

	private const int WMSZ_TOPRIGHT = 5;

	private const int WMSZ_BOTTOMLEFT = 7;

	private const int SWP_NOSIZE = 1;

	private static WndProcDelegate _wndProc;

	private static IntPtr _oldwndProcPtr;

	private static bool _init;

	private IntPtr WndProcPtr(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
	{
		if (!Screen.fullScreen)
		{
			switch (msg)
			{
			case 532u:
			{
				Rect structure2 = (Rect)Marshal.PtrToStructure(lParam, typeof(Rect));
				if (_windowLastWidth != structure2.Width || _windowLastHeight != structure2.Height)
				{
					(int, int) newWindowSize2 = GetNewWindowSize(hWnd, structure2.Width, structure2.Height);
					int item3 = newWindowSize2.Item1;
					int item4 = newWindowSize2.Item2;
					int num = (int)wParam;
					bool num2 = num == 7 || num == 1 || num == 4;
					bool flag = num == 3 || num == 4 || num == 5;
					if (num2)
					{
						structure2.Left = structure2.Right - item3;
					}
					else
					{
						structure2.Right = structure2.Left + item3;
					}
					if (flag)
					{
						structure2.Top = structure2.Bottom - item4;
					}
					else
					{
						structure2.Bottom = structure2.Top + item4;
					}
					Marshal.StructureToPtr(structure2, lParam, fDeleteOld: true);
				}
				break;
			}
			case 70u:
			{
				WindowPos structure = (WindowPos)Marshal.PtrToStructure(lParam, typeof(WindowPos));
				if ((structure.flags & 1) == 0 && (_windowLastWidth != structure.cx || _windowLastHeight != structure.cy))
				{
					(int, int) newWindowSize = GetNewWindowSize(hWnd, structure.cx, structure.cy);
					int item = newWindowSize.Item1;
					int item2 = newWindowSize.Item2;
					structure.cx = item;
					structure.cy = item2;
					Marshal.StructureToPtr(structure, lParam, fDeleteOld: true);
				}
				break;
			}
			}
		}
		return CallWindowProc(_oldwndProcPtr, hWnd, msg, wParam, lParam);
	}

	private (int, int) GetWindowFrameSize(IntPtr hWnd)
	{
		GetClientRect(hWnd, out var lpRect);
		if (lpRect.Right - lpRect.Left == 0 || lpRect.Bottom - lpRect.Top == 0)
		{
			return (_frameLastWidth, _frameLastHeight);
		}
		GetWindowRect(hWnd, out var lpRect2);
		int item = lpRect2.Right - lpRect2.Left - (lpRect.Right - lpRect.Left);
		int item2 = lpRect2.Bottom - lpRect2.Top - (lpRect.Bottom - lpRect.Top);
		return (item, item2);
	}

	private static (int, int) WindowToClientSize(int windowWidth, int windowHeight, int frameWidth, int frameHeight)
	{
		return (windowWidth - frameWidth, windowHeight - frameHeight);
	}

	private static (int, int) ClientToWindowSize(int clientWidth, int clientHeight, int frameWidth, int frameHeight)
	{
		return (clientWidth + frameWidth, clientHeight + frameHeight);
	}

	private (int, int) GetNewWindowSize(IntPtr hWnd, int width, int height)
	{
		(int, int) windowFrameSize = GetWindowFrameSize(hWnd);
		int item = windowFrameSize.Item1;
		int item2 = windowFrameSize.Item2;
		_frameLastWidth = item;
		_frameLastHeight = item2;
		(int, int) tuple = WindowToClientSize(width, height, item, item2);
		int item3 = tuple.Item1;
		int item4 = tuple.Item2;
		Vector3 fixedSize = getFixedSize(item3, item4);
		item3 = (int)fixedSize.x;
		item4 = (int)fixedSize.y;
		UpdateGame(fixedSize.z);
		_windowLastWidth = item3;
		_windowLastHeight = item4;
		return ClientToWindowSize(item3, item4, item, item2);
	}

	private void init()
	{
		if (!_init)
		{
			IntPtr activeWindow = GetActiveWindow();
			_wndProc = WndProcPtr;
			IntPtr functionPointerForDelegate = Marshal.GetFunctionPointerForDelegate(_wndProc);
			IntPtr? intPtr = SetWindowLongPtr(activeWindow, -4, functionPointerForDelegate);
			if (intPtr.HasValue)
			{
				_oldwndProcPtr = intPtr.Value;
				_init = true;
			}
		}
	}

	public WindowResize()
	{
		init();
	}

	private static Vector3 getFixedSize(int width, int height)
	{
		if (height < 59)
		{
			height = 59;
		}
		float num = (float)width / (float)height;
		if (num < 1.333f)
		{
			num = 1.333f;
			if (width < 128)
			{
				width = 128;
			}
			height = (int)((float)width / num);
		}
		else if (num > 2.1666667f)
		{
			num = 2.1666667f;
			width = (int)((float)height * num);
		}
		return new Vector3(width, height, num);
	}

	public static void SetResolution(int newWidth, int newHeight)
	{
		Vector3 fixedSize = getFixedSize(newWidth, newHeight);
		newWidth = (int)fixedSize.x;
		newHeight = (int)fixedSize.y;
		float z = fixedSize.z;
		if (Toolbox.QualityManager != null)
		{
			Toolbox.QualityManager.ChangeResolution(newWidth, newHeight, Screen.fullScreen);
		}
		UpdateGame(z);
		_windowLastWidth = Screen.width;
		_windowLastHeight = Screen.height;
	}

	private static void ResolutionChanged()
	{
		Vector3 fixedSize = getFixedSize(Screen.width, Screen.height);
		int num = (int)fixedSize.x;
		int num2 = (int)fixedSize.y;
		float z = fixedSize.z;
		if (Toolbox.QualityManager != null)
		{
			if (num != Screen.width || num2 != Screen.height)
			{
				Toolbox.QualityManager.ChangeResolution(num, num2, Screen.fullScreen);
			}
			else
			{
				Toolbox.QualityManager.UpdateFromUnity();
			}
		}
		UpdateGame(z);
		_windowLastWidth = num;
		_windowLastHeight = num2;
		_lastFullscreen = Screen.fullScreen;
	}

	private static void UpdateGame(float ratio)
	{
		if (GameMgr.GetIns() != null)
		{
			GameMgr.GetIns().ChangeAspectRatio(ratio);
		}
		if (UIManager.GetInstance() != null && UIManager.GetInstance().GetCurrentScene() == UIManager.ViewScene.Battle && BattleManagerBase.GetIns() != null)
		{
			BattleManagerBase.GetIns().ChangeCameraFieldOfView(ratio);
		}
		_requestUiUpdateFrame = Time.frameCount;
	}

	private static void UpdateUI()
	{
		UILabel[] array = UnityEngine.Object.FindObjectsOfType<UILabel>();
		for (int i = 0; i < array.Length; i++)
		{
			array[i].WrapOnResize();
			array[i].UpdateNGUIText();
		}
		UITable[] array2 = UnityEngine.Object.FindObjectsOfType<UITable>();
		for (int j = 0; j < array2.Length; j++)
		{
			array2[j].Reposition();
		}
		AspectCameraPerspective[] array3 = UnityEngine.Object.FindObjectsOfType<AspectCameraPerspective>();
		for (int k = 0; k < array3.Length; k++)
		{
			array3[k].UpdateFov();
		}
	}

	public void Update()
	{
		init();
		if (_requestUiUpdateFrame.HasValue && _requestUiUpdateFrame.Value < Time.frameCount)
		{
			UpdateUI();
			_requestUiUpdateFrame = null;
		}
		if (Screen.fullScreen && (_windowLastWidth != Screen.width || _windowLastHeight != Screen.height))
		{
			ResolutionChanged();
		}
	}

	public void SetSavedResolutionSettings()
	{
	}

	[DllImport("user32.dll")]
	private static extern IntPtr GetActiveWindow();

	[DllImport("user32.dll")]
	private static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam);

	[DllImport("user32.dll", EntryPoint = "SetWindowLong")]
	private static extern int SetWindowLong32(IntPtr hWnd, int nIndex, int dwNewLong);

	[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
	private static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, int nIndex, IntPtr dwNewLong);

	[DllImport("user32.dll")]
	private static extern bool GetWindowRect(IntPtr hwnd, out Rect lpRect);

	[DllImport("user32.dll")]
	private static extern bool GetClientRect(IntPtr hwnd, out Rect lpRect);

	public static IntPtr? SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong)
	{
		if (IntPtr.Size == 8)
		{
			return SetWindowLongPtr64(hWnd, nIndex, dwNewLong);
		}
		int num = SetWindowLong32(hWnd, nIndex, dwNewLong.ToInt32());
		if (num == 0)
		{
			return null;
		}
		return new IntPtr(num);
	}
}
