﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace VolumeControl
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public class Volume
    {
        private const int APPCOMMAND_VOLUME_MUTE = 0x80000;
        private const int APPCOMMAND_VOLUME_UP = 0xA0000;
        private const int APPCOMMAND_VOLUME_DOWN = 0x90000;
        private const int WM_APPCOMMAND = 0x319;

        [DllImport("user32.dll")]
        public static extern IntPtr SendMessageW(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);

        public void Mute()
        {
            try
            {
                SendMessageW(new WindowInteropHelper(MainWindow.win).Handle, WM_APPCOMMAND, new WindowInteropHelper(MainWindow.win).Handle, (IntPtr)APPCOMMAND_VOLUME_MUTE);
            }
            catch (Exception e)
            {
                MainWindow.msg = "Exception! " + e.Message + "\nVolumeControl can't continue to run. Tell the developer and try to restart VolumeControl.";
                MainWindow.ShowWin(false, false, true);
            }
        }

        public void VolDown()
        {
            try
            {
                SendMessageW(new WindowInteropHelper(MainWindow.win).Handle, WM_APPCOMMAND, new WindowInteropHelper(MainWindow.win).Handle, (IntPtr)APPCOMMAND_VOLUME_DOWN);
            }
            catch (Exception e)
            {
                MainWindow.msg = "Exception! " + e.Message + "\nVolumeControl can't continue to run. Tell the developer and try to restart VolumeControl.";
                MainWindow.ShowWin(false, false, true);
            }
        }

        public void VolUp()
        {
            try
            {
                SendMessageW(new WindowInteropHelper(MainWindow.win).Handle, WM_APPCOMMAND, new WindowInteropHelper(MainWindow.win).Handle, (IntPtr)APPCOMMAND_VOLUME_UP);
            }
            catch (Exception e)
            {
                MainWindow.msg = "Exception! " + e.Message + "\nVolumeControl can't continue to run. Tell the developer and try to restart VolumeControl.";
                MainWindow.ShowWin(false, false, true);
            }
        }
    }

    public partial class MainWindow : Window
    {
        int heldTime = 0;
        int volHeldTime = 0;
        public static string msg = "Message here";
        public static MainWindow win;
        bool isControlled = false;
        bool loaded = false;
        bool canBeHeld = false;

        public static void ShowWin(bool isInf, bool isBegin, bool isError) // 2 lazy 2 create new enums
        {
            try
            {
                win.txtblk.Text = msg;
                win.Top = SystemParameters.PrimaryScreenHeight - win.ActualHeight - 64;
                win.Left = SystemParameters.PrimaryScreenWidth / 2 - (win.ActualWidth / 2);
                win.Show();
                if (!isInf)
                {
                    DispatcherTimer hideTimer = new DispatcherTimer();
                    if (!isError)
                    {
                        win.BeginStoryboard(win.FindResource("Message") as System.Windows.Media.Animation.Storyboard);
                        hideTimer.Interval = new TimeSpan(0, 0, 0, 2, 250);
                    }
                    else
                    {
                        win.BeginStoryboard(win.FindResource("Error") as System.Windows.Media.Animation.Storyboard);
                        hideTimer.Interval = new TimeSpan(0, 0, 0, 6, 250);
                    }
                    if (!isBegin && !isError)
                    {
                        hideTimer.Tick += win.HideTimer_Tick;
                    }
                    else if (isBegin && !isError)
                    {
                        hideTimer.Tick += win.HideTimer_Tick1;
                    }
                    else if (!isBegin && isError)
                    {
                        hideTimer.Tick += HideTimer_Tick2;
                    }
                    hideTimer.Start();
                }
                else
                {
                    win.BeginStoryboard(win.FindResource("MessageInfIn") as System.Windows.Media.Animation.Storyboard);
                }
            }
            catch
            {
                Environment.FailFast("Fatal error: message window can't be shown for some reason");
            }
        }

        private static void HideTimer_Tick2(object sender, EventArgs e)
        {
            try
            {
                win.Close();
            }
            catch
            {
                Environment.FailFast("Fatal error: message window can't be closed for some reason");
            }
        }

        private void HideTimer_Tick1(object sender, EventArgs e)
        {
            try
            {
                Hide();
                DispatcherTimer tmr = (DispatcherTimer)sender;
                tmr.Stop();
                canBeHeld = true;
            }
            catch
            {
                Environment.FailFast("Fatal error: message window can't be hidden for some reason");
            }
        }

        public static void HideInfWin()
        {
            try
            {
                win.BeginStoryboard(win.FindResource("MessageInfOut") as System.Windows.Media.Animation.Storyboard);
                DispatcherTimer hideTimer = new DispatcherTimer()
                {
                    Interval = new TimeSpan(0, 0, 0, 0, 250)
                };
                hideTimer.Tick += win.HideTimer_Tick;
                hideTimer.Start();
            }
            catch
            {
                Environment.FailFast("Fatal error: message window can't be hidden for some reason");
            }
        }

        private void HideTimer_Tick(object sender, EventArgs e)
        {
            try
            {
                Hide();
                DispatcherTimer tmr = (DispatcherTimer)sender;
                tmr.Stop();
            }
            catch
            {
                Environment.FailFast("Fatal error: message window can't be hidden for some reason");
            }
        }

        public MainWindow()
        {
            try
            {
                win = this;
                DispatcherTimer mainTmr = new DispatcherTimer(DispatcherPriority.Input)
                {
                    Interval = new TimeSpan(0, 0, 0, 0, 1)
                };
                mainTmr.Tick += MainTmr_Tick;
                mainTmr.Start();
                msg = "VolumeControl is running\nHold Break to control the volume";
            }
            catch
            {
                Environment.FailFast("Fatal error: message window can't be initialized for some reason");
            }
        }

        private void MainTmr_Tick(object sender, EventArgs e)
        {
            try
            {
                if (Keyboard.IsKeyDown(Key.Pause) && canBeHeld)
                {
                    heldTime++;
                }
                else if (Keyboard.IsKeyUp(Key.Pause) && !canBeHeld)
                {
                    canBeHeld = true;
                }
                else
                {
                    heldTime = 0;
                }
                if (heldTime > 30)
                {
                    canBeHeld = false;
                    if (window.Visibility == Visibility.Hidden)
                    {
                        msg = "Use Up and Down to control the volume\nPress Enter to mute\nHold Break to stop controlling";
                        ShowWin(true, false, false);
                        heldTime = 0;
                        isControlled = true;
                    }
                    else
                    {
                        HideInfWin();
                        heldTime = 0;
                        volHeldTime = 0;
                        isControlled = false;
                    }
                }
                if (isControlled)
                {
                    Volume vol = new Volume();
                    if (Keyboard.IsKeyDown(Key.Up))
                    {
                        if (volHeldTime == 0)
                        {
                            vol.VolUp();
                            volHeldTime++;
                        }
                        else if (volHeldTime > 10)
                        {
                            volHeldTime = 0;
                        }
                        else
                        {
                            volHeldTime++;
                        }
                    }
                    else if (Keyboard.IsKeyDown(Key.Down))
                    {
                        if (volHeldTime == 0)
                        {
                            vol.VolDown();
                            volHeldTime++;
                        }
                        else if (volHeldTime > 10)
                        {
                            volHeldTime = 0;
                        }
                        else
                        {
                            volHeldTime++;
                        }
                    }
                    else if (Keyboard.IsKeyDown(Key.Enter))
                    {
                        if (volHeldTime == 0)
                        {
                            vol.Mute();
                            volHeldTime++;
                        }
                        else if (volHeldTime > 10)
                        {
                            volHeldTime = 0;
                        }
                        else
                        {
                            volHeldTime++;
                        }
                    }
                    else if (Keyboard.IsKeyUp(Key.Up) || Keyboard.IsKeyUp(Key.Down) || Keyboard.IsKeyUp(Key.Enter))
                    {
                        volHeldTime = 0;
                    }
                }
            }
            catch (Exception e1)
            {
                msg = "Exception! " + e1.Message + "\nVolumeControl can't continue to run. Tell the developer and try to restart VolumeControl.";
                ShowWin(false, false, true);
            }
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {
                if (!loaded)
                {
                    ShowWin(false, true, false);
                    loaded = true;
                }
            }
            catch
            {
                Environment.FailFast("Fatal error: message window can't be shown for some reason");
            }
        }

        private void window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            e.Cancel = true;
            MessageBox.Show("Use the task manager to close VolumeControl, not Alt+F4.\nIf you're killing it with task manager though, then VC will close soon...", "Accidental close prevention");
        }
    }
}
