using System;
using Systemm = System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Text;
using System.Windows.Forms;
using Forms = System.Windows.Forms;
using System.Runtime.InteropServices;
using Trigger.Classes.Screen;

namespace Trigger.Status
{
	/// <summary>
	/// <para>Provides methods to examine the status of screen devices</para>
	/// </summary>
	static class Screen
	{
		#region DllImports
		/// <summary>
		/// <para>The EnumDisplaySettings function retrieves information about one of the graphics modes for a display device. To retrieve information for all the graphics modes of a display device, make a series of calls to this function.</para>
		/// <para>The EnumDisplaySettings function sets values for the following five <see cref="ScreenSettingsDevMode"/> members:
		/// <list type="unordered"></list>
		/// <item>dmBitsPerPel</item>
		/// <item>dmPelsWidth</item>
		/// <item>dmPelsHeigh</item>t</item>
		/// <item>dmDisplayFlags</item>
		/// <item>dmDisplayFrequency</item>
		/// </para>
		/// </summary>
		/// <param name="lpszDeviceName">
		/// <para>A pointer to a null-terminated string that specifies the display device about whose graphics mode the function will obtain information.</para>
		/// <para>This parameter is either NULL or a DISPLAY_DEVICE.DeviceName returned from EnumDisplayDevices. A NULL value specifies the current display device on the computer on which the calling thread is running.</para>
		/// </param>
		/// <param name="iModeNum">The type of information to be retrieved. This value can be a graphics mode index or one of the following values.
		/// <list type="unordered">
		/// <item>ENUM_CURRENT_SETTINGS</item>
		/// <item>ENUM_REGISTRY_SETTINGS</item>
		/// </list></param>
		/// <param name="lpDevMode"><para>A pointer to a <see cref="ScreenSettingsDevMode"/> structure into which the function stores information about the specified graphics mode. Before calling EnumDisplaySettings, set the dmSize member to sizeof(DEVMODE), and set the dmDriverExtra member to indicate the size, in bytes, of the additional space available to receive private driver data.</para></param>
		/// <returns>If the function succeeds, the return value is nonzero. If the function fails, the return value is zero.</returns>
		[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
		private static extern int EnumDisplaySettings(string lpszDeviceName, int iModeNum, ref ScreenSettingsDevMode lpDevMode);
		#endregion

		#region Properties
		#region Screen
		/// <summary><para>Gets a list of all displays on the system</para></summary>
		public static List<ScreenEx> AllScreens
		{
			get
			{
				List<Forms.Screen> allScreens = new List<Forms.Screen>(Forms.Screen.AllScreens);
				List<ScreenEx> allScreensEx = new List<ScreenEx>(allScreens.Count);
				allScreens.ForEach(new Action<Forms.Screen>(screen => allScreensEx.Add(GetScreenSettings(screen))));
				return allScreensEx;
			}
		}
		/// <summary><para>Gets the primary screen</para></summary>
		public static ScreenEx PrimaryScreen
		{
			get
			{
				return GetScreenSettings(Forms.Screen.PrimaryScreen);
			}
		}

		/// <summary>
		/// <para>Gets the orientation of the screen</para>
		/// <para>But which screen?</para>
		/// </summary>
		public static ScreenOrientation ScreenOrientation
		{
			get
			{
				return SystemInformation.ScreenOrientation;
			}
		}
		#endregion
		#endregion

		#region Methods
		/// <summary>
		/// <para>Returns the current System status</para>
		/// </summary>
		/// <returns></returns>
		public static TreeNode GetStatus()
		{
			TreeNode tnMain = new TreeNode("Screens (" + AllScreens.Count + ")");
			AllScreens.ForEach(new Action<ScreenEx>(screen =>
			{
				TreeNode tnScreen = tnMain.Nodes.Add(screen.Name);
				tnScreen.Nodes.Add("Primary: " + screen.Primary.ToString());
				tnScreen.Nodes.Add("Color depth: " + screen.BitsPerPixel + "bit");
				tnScreen.Nodes.Add("Resolution: " + screen.Bounds.Width + "x" + screen.Bounds.Height);
				tnScreen.Nodes.Add("Position: " + screen.Bounds.X + " | " + screen.Bounds.Y);
				tnScreen.Nodes.Add("Display orientation: " + screen.Orientation.ToString());
				tnScreen.Nodes.Add("Refresh rate: " + screen.Frequency);
			}));
			return tnMain;
		}

		public static ScreenEx GetScreenSettings(Forms.Screen screen)
		{
			ScreenSettingsDevMode DevMode = new ScreenSettingsDevMode(true);
			if (EnumDisplaySettings(screen.DeviceName, -1 /*current settings*/, ref DevMode) == 0)
				throw new Exception("EnumDisplaySettings (user32.dll) returned 0");
			ScreenEx screenSettings = new ScreenEx(screen, DevMode);
			return screenSettings;
		}
		#endregion
	}
}
