using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Threading;
using System.Reflection;

// Ooganizer Namespaces
using Foo.Platform;
using Foo.Platform.Interacters;

namespace Foo.ClientServices.ButtonWPForm
{
    /// <summary>
    /// This class manages the creation/deletion of a Oogy CaptionButton Instance Exe.
    /// A CaptionButton Instance hosts the ButtonHook.dll
    /// </summary>
    [ComVisible(false)]
    internal class CaptionButtonStarter
    {

        // CaptionButton (ButtonHook.dll) Startup Delay
        private const int CAPTIONBUTTON_STARTUP_DELAY_MILISECONDS = 4000;

        // Member Variables
        private static Thread s_ButtonHookKeepAliveThread = null;
        private static bool s_ButtonHookKeepAliveThreadIsInitialized = false;

        // Declare the Log4net Variable
        private static log4net.ILog Log = Logger.GetLog4NetInterface(MethodBase.GetCurrentMethod().DeclaringType);

        /// <summary>
        /// Constructor by default will launch the thread if needed
        /// </summary>
        static CaptionButtonStarter()
        {
            StartButtonHookKeepAliveThreadIfNeeded();
        }

        /// <summary>
        /// Use this property to set the CaptionButton to running / not running
        /// </summary>
        public static bool Run
        {
            get { return s_ButtonHookKeepAliveThreadIsInitialized; }
            set 
            { 
                if (!value) 
                    TerminateButtonHookKeepAliveThreadIfNeeded();

                s_ButtonHookKeepAliveThreadIsInitialized = value;
            }
        }

        /// <summary>
        /// ButtonHookKeepAliveThread Thread for ButtonHook.dll - handled internally
        /// </summary>        
        private static void ButtonHookKeepAliveThreadProc()
        {
            Thread.Sleep(CAPTIONBUTTON_STARTUP_DELAY_MILISECONDS);
            while (true) // Make Sure ButtonHook stays alive (No User kills it for any reason)            
            {
                if (!BHInteracter.IsCaptionButtonRunning())
                {
                    Log.Info(string.Format("{0}() - ButtonHookKeepAliveThread - About to call StartCaptionButton()", MethodBase.GetCurrentMethod().Name));

                    // Launch OogyCaptionButton Process EXE
                    BHInteracter.StartCaptionButton();

                    // wait a little before checking again...
                    Thread.Sleep(100); 

                    if (BHInteracter.IsCaptionButtonRunning())                    
                        Log.Info(string.Format("{0}() - StartCaptionButton() Succeeded", MethodBase.GetCurrentMethod().Name));
                    else
                        Log.Error(string.Format("{0}() - StartCaptionButton() Failed", MethodBase.GetCurrentMethod().Name));
                }

                if (!s_ButtonHookKeepAliveThreadIsInitialized)
                {
                    s_ButtonHookKeepAliveThreadIsInitialized = true;
                    Log.Info(string.Format("{0}() - ButtonWPForm ButtonHookKeepAliveThread is initialized s_ButtonHookKeepAliveThreadIsInitialized is True", MethodBase.GetCurrentMethod().Name));
                }

                // Checking every 30 seconds (quickly) should be more than enough
                Thread.Sleep(30000);
            }            
        }

        /// <summary>
        /// Use this function to start ThreadProc(above) if needed. COM+ can shutdown the thread anytime,
        /// we need to make sure that the thread is alive BEFORE calling ButtonForms
        /// </summary>
        private static void StartButtonHookKeepAliveThreadIfNeeded()
        {
            if (s_ButtonHookKeepAliveThread != null && s_ButtonHookKeepAliveThread.IsAlive)
            {
                return;
            }
            else
            {
                s_ButtonHookKeepAliveThreadIsInitialized = false;

                // Start a new Thread so it can become the Message Loop
                s_ButtonHookKeepAliveThread = new Thread(new ThreadStart(CaptionButtonStarter.ButtonHookKeepAliveThreadProc));

                // GUI components require the thread to be STA; otherwise throws an error
                s_ButtonHookKeepAliveThread.SetApartmentState(ApartmentState.STA);
                s_ButtonHookKeepAliveThread.Start();                
            }
        }

        /// <summary>
        /// Terminate the ButtonHook.dll by killing the Process
        /// </summary>
        private static void TerminateButtonHookKeepAliveThreadIfNeeded()
        {
            if (s_ButtonHookKeepAliveThreadIsInitialized)
            {
                s_ButtonHookKeepAliveThread.Abort();
                s_ButtonHookKeepAliveThreadIsInitialized = false;
                Log.Info(string.Format("{0}() - ButtonWPForm is ButtonHookKeepAliveThread shutdown s_ButtonHookKeepAliveThreadIsInitialized is False", MethodBase.GetCurrentMethod().Name));

                // Kill the OogyCaptionButton Process EXE
                BHInteracter.StopCaptionButton();
            }
        }

    }
}
