using System;
using System.ComponentModel;
using System.Diagnostics;
using TweetDuck.Utils;
using TweetLib.Core.Application;

namespace TweetDuck.Application{
    class LockHandler : IAppLockHandler{
        private const int WaitRetryDelay = 250;
        private const int RestoreFailTimeout = 2000;
        private const int CloseNaturallyTimeout = 10000;
        private const int CloseKillTimeout = 5000;

        bool IAppLockHandler.RestoreProcess(Process process){
            if (process.MainWindowHandle == IntPtr.Zero){ // restore if the original process is in tray
                NativeMethods.BroadcastMessage(Program.WindowRestoreMessage, (uint)process.Id, 0);

                if (WindowsUtils.TrySleepUntil(() => CheckProcessExited(process) || (process.MainWindowHandle != IntPtr.Zero && process.Responding), RestoreFailTimeout, WaitRetryDelay)){
                    return true;
                }
            }

            return false;
        }

        bool IAppLockHandler.CloseProcess(Process process){
            try{
                if (process.CloseMainWindow()){
                    // ReSharper disable once AccessToDisposedClosure
                    WindowsUtils.TrySleepUntil(() => CheckProcessExited(process), CloseNaturallyTimeout, WaitRetryDelay);
                }

                if (!process.HasExited){
                    process.Kill();
                    // ReSharper disable once AccessToDisposedClosure
                    WindowsUtils.TrySleepUntil(() => CheckProcessExited(process), CloseKillTimeout, WaitRetryDelay);
                }

                if (process.HasExited){
                    process.Dispose();
                    return true;
                }
                else{
                    return false;
                }
            }catch(Exception ex) when (ex is InvalidOperationException || ex is Win32Exception){
                bool hasExited = CheckProcessExited(process);
                process.Dispose();
                return hasExited;
            }
        }

        private static bool CheckProcessExited(Process process){
            process.Refresh();
            return process.HasExited;
        }
    }
}