using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace NewPosInstaller
{
    public class DisplayInfo
    {
        [DllImport("User32.dll")]
        private static extern bool EnumDisplayDevices(IntPtr lpDevice, int iDevNum, ref DISPLAY_DEVICE lpDisplayDevice, int dwFlags);
        [DllImport("User32.dll")]
        private static extern bool EnumDisplaySettings(string devName, int modeNum, ref DEVMODE devMode);
        [DllImport("user32.dll")]
        private static extern int ChangeDisplaySettings(ref DEVMODE devMode, int flags);


        [StructLayout(LayoutKind.Sequential)]
        private struct DISPLAY_DEVICE
        {
            public int cb;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
            public string DeviceName;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
            public string DeviceString;
            public int StateFlags;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
            public string DeviceID;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
            public string DeviceKey;

            public DISPLAY_DEVICE(int flags)
            {
                cb = 0;
                StateFlags = flags;
                DeviceName = new string((char)32, 32);
                DeviceString = new string((char)32, 128);
                DeviceID = new string((char)32, 128);
                DeviceKey = new string((char)32, 128);
                cb = Marshal.SizeOf(this);
            }
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct DEVMODE
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
            public string dmDeviceName;
            public short dmSpecVersion;
            public short dmDriverVersion;
            public short dmSize;
            public short dmDriverExtra;
            public int dmFields;
            public short dmOrientation;
            public short dmPaperSize;
            public short dmPaperLength;
            public short dmPaperWidth;
            public short dmScale;
            public short dmCopies;
            public short dmDefaultSource;
            public short dmPrintQuality;
            public short dmColor;
            public short dmDuplex;
            public short dmYResolution;
            public short dmTTOption;
            public short dmCollate;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
            public string dmFormName;
            public short dmUnusedPadding;
            public short dmBitsPerPel;
            public int dmPelsWidth;
            public int dmPelsHeight;
            public int dmDisplayFlags;
            public int dmDisplayFrequency;
        }

        public class DisplayDevice
        {
            public string DeviceID = string.Empty;
            public string DeviceKey = string.Empty; 
            public string DeviceName = string.Empty;
            public string DeviceString = string.Empty;
            public int StatusFlags;
            public bool Primary = false;
            public int DeviceNum; 
        }

        public class DeviceMode
        {
            public string DeviceName = string.Empty;
            public int SpecVersion;
            public int DriverVersion;
            public int Size;
            public int DriverExtra;
            public int Fields;
            public int Orientation;
            public int PaperSize;
            public int PaperLength;
            public int PaperWidth;
            public int Scale;
            public int Copies;
            public int DefaultSource;
            public int PrintQuality;
            public int Color;
            public int Duplex;
            public int YResolution;
            public int TTOption;
            public int Collate;
            public string FormName = string.Empty;
            public int UnusedPadding;
            public int BitsPerPel;
            public int PelsWidth;
            public int PelsHeight;
            public int DisplayFlags;
            public int DisplayFrequency;

            public override string ToString()
            {
                return string.Format("{0}x{1}, {2}bits, {3}Hz"
                                    , PelsWidth.ToString()
                                    , PelsHeight.ToString()
                                    , BitsPerPel.ToString()
                                    , DisplayFrequency.ToString());
            }
        }


        public List<DisplayDevice> GetDisplayDevice()
        {
            List<DisplayDevice> deviceList = new List<DisplayDevice>();

            try
            {
                int devNum = 0;
                bool result;

                do
                {
                    DISPLAY_DEVICE d = new DISPLAY_DEVICE(0);
                    result = EnumDisplayDevices(IntPtr.Zero, devNum, ref d, 0);

                    if (result)
                    {
                        DisplayDevice dev = new DisplayDevice();
                        dev.DeviceNum = devNum;
                        dev.DeviceID = d.DeviceID.Trim();
                        dev.DeviceKey = d.DeviceKey.Trim();
                        dev.DeviceName = d.DeviceName.Trim();
                        dev.DeviceString = d.DeviceString.Trim();
                        dev.StatusFlags = d.StateFlags;
                        dev.Primary = IsPrimaryDevice(devNum);

                        deviceList.Add(dev);
                    }

                    devNum++;

                } while (result);

            }
            catch (Exception ex)
            {
                ComLog.WriteLog(ComLog.Level.Exception
                              , System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name + "."
                              + System.Reflection.MethodBase.GetCurrentMethod().Name + "()"
                              , ex.Message);
                deviceList.Clear();
            }
            return deviceList;
        }

        public List<DeviceMode> GetDeviceMode(int devNum)
        {
            List<DeviceMode> devModeList = new List<DeviceMode>();
            try
            {
                int modeNum = 0;
                bool result;

                do
                {
                    DeviceMode dm = GetDeviceMode(devNum, modeNum);
                    result = dm != null ? true : false;
                    if (result)
                        devModeList.Add(dm);

                    modeNum++;

                } while (result);

            }
            catch (Exception ex)
            {
                ComLog.WriteLog(ComLog.Level.Exception
                              , System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name + "."
                              + System.Reflection.MethodBase.GetCurrentMethod().Name + "()"
                              , ex.Message);
                devModeList.Clear();
            }
            return devModeList;
        }

        public DeviceMode GetDeviceMode(int devNum, int modeNum)
        {
            try
            {
                DeviceMode deviceMode = new DeviceMode();

                string devName = GetDeviceName(devNum);
                DEVMODE dm = new DEVMODE();

                bool ret = EnumDisplaySettings(devName, modeNum, ref dm);
                if (ret == false) return null; 

                deviceMode.DeviceName = dm.dmDeviceName.Trim();
                deviceMode.SpecVersion = dm.dmSpecVersion;
                deviceMode.DriverVersion = dm.dmDriverVersion;
                deviceMode.Size = dm.dmSize;
                deviceMode.DriverExtra = dm.dmDriverExtra;
                deviceMode.Fields = dm.dmFields;
                deviceMode.Orientation = dm.dmOrientation;
                deviceMode.PaperSize = dm.dmPaperSize;
                deviceMode.PaperLength = dm.dmPaperLength;
                deviceMode.PaperWidth = dm.dmPaperWidth;
                deviceMode.Scale = dm.dmScale;
                deviceMode.Copies = dm.dmCopies;
                deviceMode.DefaultSource = dm.dmDefaultSource;
                deviceMode.PrintQuality = dm.dmPrintQuality;
                deviceMode.Color = dm.dmColor;
                deviceMode.Duplex = dm.dmDuplex;
                deviceMode.YResolution = dm.dmYResolution;
                deviceMode.TTOption = dm.dmTTOption;
                deviceMode.Collate = dm.dmCollate;
                deviceMode.FormName = dm.dmFormName.Trim();
                deviceMode.UnusedPadding = dm.dmUnusedPadding;
                deviceMode.BitsPerPel = dm.dmBitsPerPel;
                deviceMode.PelsWidth = dm.dmPelsWidth;
                deviceMode.PelsHeight = dm.dmPelsHeight;
                deviceMode.DisplayFlags = dm.dmDisplayFlags;
                deviceMode.DisplayFrequency = dm.dmDisplayFrequency;

                return deviceMode;
            }
            catch (Exception ex)
            {
                ComLog.WriteLog(ComLog.Level.Exception
                              , System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name + "."
                              + System.Reflection.MethodBase.GetCurrentMethod().Name + "()"
                              , ex.Message);
                return null; 
            }
        }

        public string GetDeviceName(int devNum)
        {
            string deviceName = string.Empty;
            try
            {
                DISPLAY_DEVICE d = new DISPLAY_DEVICE(0);
                bool result = EnumDisplayDevices(IntPtr.Zero, devNum, ref d, 0);
                deviceName = result ? d.DeviceName.Trim() : "#error#";
            }
            catch (Exception ex)
            {
                ComLog.WriteLog(ComLog.Level.Exception
                              , System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name + "."
                              + System.Reflection.MethodBase.GetCurrentMethod().Name + "()"
                              , ex.Message);
            }
            return deviceName; 
        }

        public bool IsPrimaryDevice(int devNum)
        {
            DISPLAY_DEVICE d = new DISPLAY_DEVICE(0);
            if (EnumDisplayDevices(IntPtr.Zero, devNum, ref d, 0))
            {
                return ((d.StateFlags & 4) != 0);
            }
            return false;   
        }
    }
}
