using System;
using System.Configuration;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows;
using System.Windows.Forms;

namespace Timelapser
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        GlobalInput _input = new GlobalInput();

        uint _imageNr = 0;
        bool _running = false;
        bool _away = false;

        float _awayDelay;
        float _atDelay;
        string _targetPath;

        System.Timers.Timer _captureTimer = new System.Timers.Timer(500);
        DateTime _lastImage;

        public MainWindow()
        {
            InitializeComponent();

            _captureTimer.Elapsed += _captureTimer_Elapsed;
            _captureTimer.AutoReset = true;

            _captureTimer.Start();

            var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoaming);
            
            if (config.Sections["TimelapserSettings"] == null)
            {
                var section = new TimelapserSettings();
                section.SectionInformation.AllowExeDefinition = ConfigurationAllowExeDefinition.MachineToLocalUser;
                section.SectionInformation.ForceSave = true;

                config.Sections.Add("TimelapserSettings", section);
                config.Save(ConfigurationSaveMode.Full);
            }

            var settings = config.GetSection("TimelapserSettings") as TimelapserSettings;

            AtComputerTime.Value = settings.AtComputer;
            AwayComputerTime.Value = settings.AwayComputer;
            TargetPath.Text = settings.TargetPath;
            
            if (System.IO.File.Exists(TargetPath.Text + "\\image_00000.png"))
                do
                {
                    _imageNr += 1;
                }
                while (System.IO.File.Exists(TargetPath.Text + "\\image_" + _imageNr.ToString("00000") + ".png"));
        }

        private void _captureTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (!_running)
                return;

            /// TODO: UI these
            var mDiff = DateTime.Now - _input.MouseTime > TimeSpan.FromSeconds(_awayDelay);
            var kDiff = DateTime.Now - _input.KeyboardTime > TimeSpan.FromSeconds(_awayDelay);
            
            _away = mDiff && kDiff;
            
            var diff = DateTime.Now - _lastImage;
            if (diff > TimeSpan.FromSeconds(_away ? _awayDelay : _atDelay))
            {
                _lastImage = DateTime.Now;
                var bounds = Screen.PrimaryScreen.Bounds;

                using (var bitmap = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format32bppArgb))
                {
                    using (var graphics = Graphics.FromImage(bitmap))
                    {
                        graphics.CopyFromScreen(bounds.Location, new System.Drawing.Point(0, 0), bounds.Size);
                    }

                    ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
                    int j = 0;
                    for (j = 0; j < codecs.Length; j++)
                    {
                        if (codecs[j].MimeType == "image/png") break;
                    }
                    EncoderParameter ratio = new EncoderParameter(Encoder.Quality, 50L);
                    EncoderParameters CodecParams = new EncoderParameters(1);
                    CodecParams.Param[0] = ratio;

                    bitmap.Save(_targetPath + "\\image_" + _imageNr.ToString("00000") + ".png", codecs[j], CodecParams);
                    _imageNr += 1;
                }
            }
        }

        private void BrowseButton_Click(object sender, RoutedEventArgs e)
        {
            var dialog = new FolderBrowserDialog();
            dialog.Description = "Choose where to store the timelapse images.";
            DialogResult result = dialog.ShowDialog(this.GetIWin32Window());

            if (result == System.Windows.Forms.DialogResult.OK)
            {
                TargetPath.Text = dialog.SelectedPath;
            }
        }

        private void StartStopButton_Click(object sender, RoutedEventArgs e)
        {
            if (!_running && !System.IO.Directory.Exists(TargetPath.Text))
            {
                System.Windows.MessageBox.Show("Please specify a correct target path first.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

            _awayDelay = (float)AwayComputerTime.Value;
            _atDelay = (float)AtComputerTime.Value;
            _targetPath = TargetPath.Text;

            if (_awayDelay < _atDelay)
            {
                System.Windows.MessageBox.Show("You can't have it that way, sorry.");
                return;
            }

            _running = !_running;

            StartStopButton.Content = (_running ? "Stop" : "Start");
            TargetPath.IsEnabled = !_running;
            BrowseButton.IsEnabled = !_running;
            AtComputerTime.IsEnabled = !_running;
            AwayComputerTime.IsEnabled = !_running;

            TrayIcon.ToolTipText = "Timelapser (" + (_running ? "Running" : "Stopped") + ")";
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (_running)
            {
                MessageBoxResult result = System.Windows.MessageBox.Show("This will abort the livestream", "Warning", MessageBoxButton.OKCancel, MessageBoxImage.Exclamation);
                if (result == MessageBoxResult.Cancel)
                {
                    e.Cancel = true;
                    return;
                }
            }

            _running = false;

            var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoaming);
            var settings = config.GetSection("TimelapserSettings") as TimelapserSettings;

            settings.AtComputer = (int)AtComputerTime.Value;
            settings.AwayComputer = (int)AwayComputerTime.Value;
            settings.TargetPath = TargetPath.Text;
            
            config.Save(ConfigurationSaveMode.Modified);
        }

        private void Window_StateChanged(object sender, EventArgs e)
        {
            switch (WindowState)
            {
                case WindowState.Minimized:
                    Hide();
                    TrayIcon.Visibility = Visibility.Visible;
                    break;
            }
        }

        private void TrayIcon_TrayMouseDoubleClick(object sender, RoutedEventArgs e)
        {
            Show();
            WindowState = WindowState.Normal;

            Activate();
            TrayIcon.Visibility = Visibility.Hidden;
        }
    }

    
    public sealed class TimelapserSettings : ConfigurationSection
    {
        public TimelapserSettings()
        {
        }

        [ConfigurationProperty("atComputer", DefaultValue = 10)]
        [IntegerValidator(MinValue = 0)]
        public int AtComputer
        { 
            get { return (int)this["atComputer"]; }
            set { this["atComputer"] = value; }
        }
        [ConfigurationProperty("awayComputer", DefaultValue = 60)]
        [IntegerValidator(MinValue = 0)]
        public int AwayComputer
        {
            get { return (int)this["awayComputer"]; }
            set { this["awayComputer"] = value; }
        }
        [ConfigurationProperty("targetPath", DefaultValue = "C:\\Timelapse")]
        public string TargetPath
        {
            get { return (string)this["targetPath"]; }
            set { this["targetPath"] = value; }
        }
    }

    public static class MyWpfExtensions
    {
        public static System.Windows.Forms.IWin32Window GetIWin32Window(this System.Windows.Media.Visual visual)
        {
            var source = System.Windows.PresentationSource.FromVisual(visual) as System.Windows.Interop.HwndSource;
            System.Windows.Forms.IWin32Window win = new OldWindow(source.Handle);
            return win;
        }

        private class OldWindow : System.Windows.Forms.IWin32Window
        {
            private readonly System.IntPtr _handle;
            public OldWindow(System.IntPtr handle)
            {
                _handle = handle;
            }

            #region IWin32Window Members
            System.IntPtr System.Windows.Forms.IWin32Window.Handle
            {
                get { return _handle; }
            }
            #endregion
        }
    }
}
