using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

namespace AlyiosWindowsHelper
{
    class Program
    {
        [DllImport("user32.dll")]
        static extern bool SetProcessDPIAware();

        [STAThread]
        static int Main(string[] args)
        {
            // Enable DPI awareness
            SetProcessDPIAware();
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            if (args.Length < 1)
            {
                Console.Error.WriteLine("Usage: WindowsHelper <command> [options]");
                Console.Error.WriteLine("Commands: clipboard, screenshot, notify, audio, display");
                return 1;
            }

            string command = args[0].ToLower();

            try
            {
                switch (command)
                {
                    case "clipboard":
                        return HandleClipboard(args);
                    case "screenshot":
                        return HandleScreenshot(args);
                    case "notify":
                        return HandleNotification(args);
                    case "audio":
                        return HandleAudio(args);
                    case "display":
                        return HandleDisplay(args);
                    case "pixel":
                        return HandlePixel(args);
                    default:
                        Console.Error.WriteLine("Unknown command: " + command);
                        return 1;
                }
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine("Error: " + ex.Message);
                return 1;
            }
        }

        #region Clipboard Operations

        static int HandleClipboard(string[] args)
        {
            if (args.Length < 2)
            {
                Console.Error.WriteLine("Usage: clipboard <get|set|clear|getfiles|setfiles>");
                return 1;
            }

            string action = args[1].ToLower();

            switch (action)
            {
                case "get":
                    return ClipboardGet();
                case "set":
                    return ClipboardSet(args);
                case "clear":
                    return ClipboardClear();
                case "getfiles":
                    return ClipboardGetFiles();
                case "setfiles":
                    return ClipboardSetFiles(args);
                default:
                    Console.Error.WriteLine("Unknown clipboard action: " + action);
                    return 1;
            }
        }

        static int ClipboardGet()
        {
            if (Clipboard.ContainsText())
            {
                Console.WriteLine(Clipboard.GetText());
                return 0;
            }
            return 2; // No text in clipboard
        }

        static int ClipboardSet(string[] args)
        {
            if (args.Length < 3)
            {
                Console.Error.WriteLine("Usage: clipboard set <text>");
                return 1;
            }

            string text = string.Join(" ", args.Skip(2));
            Clipboard.SetText(text);
            return 0;
        }

        static int ClipboardClear()
        {
            Clipboard.Clear();
            return 0;
        }

        static int ClipboardGetFiles()
        {
            if (Clipboard.ContainsFileDropList())
            {
                var files = Clipboard.GetFileDropList();
                foreach (string file in files)
                {
                    Console.WriteLine(file);
                }
                return 0;
            }
            return 2; // No files in clipboard
        }

        static int ClipboardSetFiles(string[] args)
        {
            if (args.Length < 3)
            {
                Console.Error.WriteLine("Usage: clipboard setfiles <file1> [file2] ...");
                return 1;
            }

            var files = new System.Collections.Specialized.StringCollection();
            for (int i = 2; i < args.Length; i++)
            {
                if (File.Exists(args[i]) || Directory.Exists(args[i]))
                {
                    files.Add(args[i]);
                }
            }

            if (files.Count > 0)
            {
                Clipboard.SetFileDropList(files);
                return 0;
            }

            Console.Error.WriteLine("No valid files provided");
            return 1;
        }

        #endregion

        #region Screenshot

        static int HandleScreenshot(string[] args)
        {
            if (args.Length < 2)
            {
                Console.Error.WriteLine("Usage: screenshot <filepath> [--screen=0] [--region=x,y,w,h]");
                return 1;
            }

            string filepath = args[1];
            int screenIndex = 0;
            Rectangle? region = null;

            // Parse options
            for (int i = 2; i < args.Length; i++)
            {
                if (args[i].StartsWith("--screen="))
                {
                    screenIndex = int.Parse(args[i].Substring(9));
                }
                else if (args[i].StartsWith("--region="))
                {
                    var parts = args[i].Substring(9).Split(',');
                    if (parts.Length == 4)
                    {
                        region = new Rectangle(
                            int.Parse(parts[0]),
                            int.Parse(parts[1]),
                            int.Parse(parts[2]),
                            int.Parse(parts[3])
                        );
                    }
                }
            }

            // Get screen bounds
            Rectangle bounds;
            if (region.HasValue)
            {
                bounds = region.Value;
            }
            else if (screenIndex < Screen.AllScreens.Length)
            {
                bounds = Screen.AllScreens[screenIndex].Bounds;
            }
            else
            {
                Console.Error.WriteLine("Invalid screen index");
                return 1;
            }

            // Capture screenshot
            using (Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height))
            {
                using (Graphics g = Graphics.FromImage(bitmap))
                {
                    g.CopyFromScreen(bounds.Left, bounds.Top, 0, 0, bounds.Size);
                }

                // Determine format from extension
                ImageFormat format = ImageFormat.Png;
                string ext = Path.GetExtension(filepath).ToLower();
                if (ext == ".jpg" || ext == ".jpeg")
                    format = ImageFormat.Jpeg;
                else if (ext == ".bmp")
                    format = ImageFormat.Bmp;
                else if (ext == ".gif")
                    format = ImageFormat.Gif;

                bitmap.Save(filepath, format);
            }

            Console.WriteLine(filepath);
            return 0;
        }

        #endregion

        #region Notifications

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

        [DllImport("user32.dll")]
        static extern bool SetForegroundWindow(IntPtr hWnd);

        static int HandleNotification(string[] args)
        {
            if (args.Length < 3)
            {
                Console.Error.WriteLine("Usage: notify <title> <message> [--icon=info|warning|error] [--timeout=5000]");
                return 1;
            }

            string title = args[1];
            string message = args[2];
            ToolTipIcon icon = ToolTipIcon.Info;
            int timeout = 5000;

            // Parse options
            for (int i = 3; i < args.Length; i++)
            {
                if (args[i].StartsWith("--icon="))
                {
                    string iconType = args[i].Substring(7).ToLower();
                    switch (iconType)
                    {
                        case "warning":
                            icon = ToolTipIcon.Warning;
                            break;
                        case "error":
                            icon = ToolTipIcon.Error;
                            break;
                        case "none":
                            icon = ToolTipIcon.None;
                            break;
                        default:
                            icon = ToolTipIcon.Info;
                            break;
                    }
                }
                else if (args[i].StartsWith("--timeout="))
                {
                    timeout = int.Parse(args[i].Substring(10));
                }
            }

            // Create notification
            using (NotifyIcon notifyIcon = new NotifyIcon())
            {
                notifyIcon.Icon = SystemIcons.Application;
                notifyIcon.Visible = true;
                notifyIcon.ShowBalloonTip(timeout, title, message, icon);

                // Keep process alive for the duration
                System.Threading.Thread.Sleep(timeout + 500);
                notifyIcon.Visible = false;
            }

            return 0;
        }

        #endregion

        #region Audio Control

        [DllImport("winmm.dll")]
        static extern int waveOutGetVolume(IntPtr hwo, out uint dwVolume);

        [DllImport("winmm.dll")]
        static extern int waveOutSetVolume(IntPtr hwo, uint dwVolume);

        static int HandleAudio(string[] args)
        {
            if (args.Length < 2)
            {
                Console.Error.WriteLine("Usage: audio <get|set|mute|unmute>");
                return 1;
            }

            string action = args[1].ToLower();

            switch (action)
            {
                case "get":
                    return AudioGetVolume();
                case "set":
                    return AudioSetVolume(args);
                case "mute":
                    return AudioMute();
                case "unmute":
                    return AudioUnmute();
                default:
                    Console.Error.WriteLine("Unknown audio action: " + action);
                    return 1;
            }
        }

        static int AudioGetVolume()
        {
            uint volume;
            waveOutGetVolume(IntPtr.Zero, out volume);

            // Extract left channel volume (lower 16 bits)
            uint leftVolume = volume & 0x0000ffff;

            // Convert to percentage (0-100)
            int percentage = (int)((leftVolume / 65535.0) * 100);

            Console.WriteLine(percentage);
            return 0;
        }

        static int AudioSetVolume(string[] args)
        {
            if (args.Length < 3)
            {
                Console.Error.WriteLine("Usage: audio set <0-100>");
                return 1;
            }

            int percentage = int.Parse(args[2]);
            if (percentage < 0) percentage = 0;
            if (percentage > 100) percentage = 100;

            // Convert percentage to volume value
            uint volumeValue = (uint)((percentage / 100.0) * 65535);

            // Set both channels to same volume
            uint volume = (volumeValue << 16) | volumeValue;

            waveOutSetVolume(IntPtr.Zero, volume);
            return 0;
        }

        static int AudioMute()
        {
            waveOutSetVolume(IntPtr.Zero, 0);
            return 0;
        }

        static int AudioUnmute()
        {
            // Set to 50% volume
            uint volumeValue = 32767;
            uint volume = (volumeValue << 16) | volumeValue;
            waveOutSetVolume(IntPtr.Zero, volume);
            return 0;
        }

        #endregion

        #region Display Info

        static int HandleDisplay(string[] args)
        {
            if (args.Length < 2)
            {
                Console.Error.WriteLine("Usage: display <info|list|primary>");
                return 1;
            }

            string action = args[1].ToLower();

            switch (action)
            {
                case "info":
                    return DisplayInfo();
                case "list":
                    return DisplayList();
                case "primary":
                    return DisplayPrimary();
                default:
                    Console.Error.WriteLine("Unknown display action: " + action);
                    return 1;
            }
        }

        static int DisplayInfo()
        {
            var screens = Screen.AllScreens;
            Console.WriteLine("ScreenCount=" + screens.Length);

            for (int i = 0; i < screens.Length; i++)
            {
                var screen = screens[i];
                Console.WriteLine(string.Format("Screen{0}_Bounds={1},{2},{3},{4}", i, screen.Bounds.X, screen.Bounds.Y, screen.Bounds.Width, screen.Bounds.Height));
                Console.WriteLine(string.Format("Screen{0}_WorkingArea={1},{2},{3},{4}", i, screen.WorkingArea.X, screen.WorkingArea.Y, screen.WorkingArea.Width, screen.WorkingArea.Height));
                Console.WriteLine(string.Format("Screen{0}_Primary={1}", i, screen.Primary));
                Console.WriteLine(string.Format("Screen{0}_BitsPerPixel={1}", i, screen.BitsPerPixel));
                Console.WriteLine(string.Format("Screen{0}_DeviceName={1}", i, screen.DeviceName));
            }

            return 0;
        }

        static int DisplayList()
        {
            var screens = Screen.AllScreens;
            for (int i = 0; i < screens.Length; i++)
            {
                var screen = screens[i];
                string primary = screen.Primary ? " (Primary)" : "";
                Console.WriteLine(string.Format("Screen {0}: {1}x{2} at ({3},{4}){5}", i, screen.Bounds.Width, screen.Bounds.Height, screen.Bounds.X, screen.Bounds.Y, primary));
            }
            return 0;
        }

        static int DisplayPrimary()
        {
            var primary = Screen.PrimaryScreen;
            Console.WriteLine(string.Format("{0}x{1}", primary.Bounds.Width, primary.Bounds.Height));
            return 0;
        }

        #endregion

        #region Pixel Operations

        [DllImport("user32.dll")]
        static extern IntPtr GetDC(IntPtr hwnd);

        [DllImport("user32.dll")]
        static extern int ReleaseDC(IntPtr hwnd, IntPtr hdc);

        [DllImport("gdi32.dll")]
        static extern uint GetPixel(IntPtr hdc, int x, int y);

        static int HandlePixel(string[] args)
        {
            if (args.Length < 2)
            {
                Console.Error.WriteLine("Usage: pixel <get> <x> <y>");
                return 1;
            }

            string action = args[1].ToLower();

            switch (action)
            {
                case "get":
                    if (args.Length < 4)
                    {
                        Console.Error.WriteLine("Usage: pixel get <x> <y>");
                        return 1;
                    }
                    return GetPixelColor(int.Parse(args[2]), int.Parse(args[3]));
                default:
                    Console.Error.WriteLine("Unknown pixel action: " + action);
                    return 1;
            }
        }

        static int GetPixelColor(int x, int y)
        {
            IntPtr hdc = GetDC(IntPtr.Zero);
            try
            {
                uint pixel = GetPixel(hdc, x, y);

                // Extract RGB values from the pixel
                int r = (int)(pixel & 0x000000FF);
                int g = (int)((pixel & 0x0000FF00) >> 8);
                int b = (int)((pixel & 0x00FF0000) >> 16);

                Console.WriteLine(string.Format("{0},{1},{2}", r, g, b));
                return 0;
            }
            finally
            {
                ReleaseDC(IntPtr.Zero, hdc);
            }
        }

        #endregion
    }
}
