using FSI.Lib.MVVM;
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;

namespace FSI.Lib.Guis.SieTiaWinCCMsgMgt
{
    public class ViewModel : MVVM.ViewModelBase
    {
        [DllImport("user32.dll")]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

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

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);


        [DllImport("user32.dll")]
        static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

        [DllImport("user32.dll")]
        static extern IntPtr PostMessage(IntPtr hwndParent, int msg, int wParam, IntPtr lParam);

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]

        static extern bool IsWindowVisible(IntPtr hWnd);

        const int BM_CLICK = 0x00F5; //message for Click which is a constant
 
        private CancellationTokenSource tokenSource = null;
        private Task task = null;

        private readonly BackgroundWorker backgroundWorker;
        private ICommand _cmdStart;
        private ICommand _cmdStop;

        
        public ViewModel()
        {
            _cmdStart = new RelayCommand<object>(ExecuteStart, CanExecuteStart);
            _cmdStop = new RelayCommand<object>(ExecuteStop, CanExecuteStop);

            backgroundWorker = new BackgroundWorker
            {
                WorkerReportsProgress = true,
                WorkerSupportsCancellation = true
            };
            backgroundWorker.DoWork += BackgroundWorker_DoWork;
            backgroundWorker.ProgressChanged += BackgroundWorker_ProgressChanged; ;
        }
        
        public IInterface Data { get; set; }

        public void Init()
        {
            if (Data.AutoStart)
            {
                ExecuteStart(null);
            }
        }

        public ICommand CmdStart
        {
            get { return _cmdStart; }
            set => _cmdStart = value;
        }

        private bool CanExecuteStop(object obj)
        {
            return Status;
        }

        private void ExecuteStop(object obj)
        {
            if (backgroundWorker.WorkerSupportsCancellation == true)
            {
                backgroundWorker.CancelAsync();
            }
            Status = false;
        }

        public ICommand CmdStop
        {
            get { return _cmdStop; }
            set => _cmdStop = value;
        }

        private bool CanExecuteStart(object obj)
        {
            return !Status;
        }

        private void ExecuteStart(object obj)
        {
            if (backgroundWorker.IsBusy != true)
            {
                backgroundWorker.RunWorkerAsync();
            }
            Status = true;
        }

        private void BackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            throw new NotImplementedException();
        }

        private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;

            while (true)
            {
                if (worker.CancellationPending == true)
                {
                    e.Cancel = true;
                    break;
                }
                else
                {
                    // Perform a time consuming operation and report progress.
                    Thread.Sleep(Data.UpdateIntervall);

                    // Find windos by Name
                    var windowHandle = FindWindow(Data.WindowsClassName, Data.WindowsName);

                    if (windowHandle != IntPtr.Zero && IsWindowVisible(windowHandle))
                    {
                        SetForegroundWindow(windowHandle);
                        var btnHandle = FindWindowEx(windowHandle, IntPtr.Zero, null, Data.ButtonName);
                        SendMessage(btnHandle, BM_CLICK, IntPtr.Zero, IntPtr.Zero);
                    }
                }
            }
        }

        public bool Status { get; set; }

        protected virtual void Dispose(bool disposing)
        {
            bool disposedValue = false;

            try
            {
                if (!disposedValue)
                {
                    if (disposing)
                    {
                        tokenSource.Cancel();
                        task.Wait();
                        tokenSource.Dispose();
                        task.Dispose();
                    }

                    disposedValue = true;
                }
            }
            catch
            {
            }
            finally
            {
                tokenSource = null;
                task = null;
            }
        }
    }
}
