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 System.Windows.Threading;

namespace Foo.ClientServices.GUIWPForms
{
    /// <summary>
    /// This class is responsible for creation and deltion of ButtonFormMgr.cs on a 
    /// Dispatcher Thread. ~The Dispatcher is responsible for all the messages being passed 
    /// for the Form Objects, it must be running at all times and created before any forms get
    /// created.
    /// </summary>
    [ComVisible(false)]
    class DispatcherThread
    {

        // Member Variables
        private static Thread s_DispatcherThread = null;
        private static bool s_DispatcherThreadIsInitialized = false;
        internal static GUIFormsMgr s_GUIFormsMgr = null;

        // 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 DispatcherThread()
        {
            Log.Info(string.Format("{0}() - DispatcherThread() called", MethodBase.GetCurrentMethod().Name));
            StartDispatcherThreadIfNeeded();
        }

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

                s_DispatcherThreadIsInitialized = value;
            }
        }

        /// <summary>
        /// Message Loop Thread for wpfGUIForms
        /// </summary>        
        private static void DispatcherThreadProc()
        {
            // Create ButtonFormMgr Object on this thread *Allow global access to the object*
            Log.Info(string.Format("{0}() - About to new GUIFormsMgr via DispatcherThread", MethodBase.GetCurrentMethod().Name));
            s_GUIFormsMgr = new GUIFormsMgr(Dispatcher.CurrentDispatcher);

            Log.Info(string.Format("{0}() - GUIFormsMgr DispatcherThread is initialized s_DispatcherThreadIsInitialized is True", MethodBase.GetCurrentMethod().Name));
            s_DispatcherThreadIsInitialized = true; // always set to true to allow caller to exit out

            if (s_GUIFormsMgr != null)
            {
                Log.Info(string.Format("{0}() - GUIFormsMgr Launched via DispatcherThread", MethodBase.GetCurrentMethod().Name));

                //Enter Dispatcher Message Loop
                System.Windows.Threading.Dispatcher.Run();
            }
            else
            {
                Log.Error(string.Format("{0}() - GUIFormsMgr Launch Failed! Exiting Thread - Major Error must have occured", MethodBase.GetCurrentMethod().Name));
                // exit thread - no need to stay here
            }
        }

        /// <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 StartDispatcherThreadIfNeeded()
        {
            if (s_DispatcherThread != null && s_DispatcherThread.IsAlive)
            {
                return;
            }
            else
            {
                s_DispatcherThreadIsInitialized = false;

                // Start a new Thread so it can become the Message Loop
                s_DispatcherThread = new Thread(new ThreadStart(DispatcherThread.DispatcherThreadProc));

                // GUI components require the thread to be STA; otherwise throws an error
                s_DispatcherThread.SetApartmentState(ApartmentState.STA);
                Log.Info(string.Format("{0}() - Starting DispatcherThread...", MethodBase.GetCurrentMethod().Name));
                s_DispatcherThread.Start();
                Log.Info(string.Format("{0}() - DispatcherThread Started.", MethodBase.GetCurrentMethod().Name));

                // Make sure the Application Object is running 
                // (COM will eventually just time out otherwise)
                //while (!s_DispatcherThreadIsInitialized)
                //    System.Threading.Thread.Sleep(20); // Syncronous call                
            }
        }

        /// <summary>
        /// Terminates all ButtonForm Objects and the Message Dispatcher Thread *do this only on shutdown*
        /// </summary>
        private static void TerminateDispatcherThreadIfNeeded()
        {
            if (s_DispatcherThreadIsInitialized)
            {
                // Delete s_GUIFormsMgr and all wpfForms from this thread
                s_GUIFormsMgr.TerminateDISP();
                s_GUIFormsMgr = null;

                s_DispatcherThread.Abort();
                s_DispatcherThreadIsInitialized = false;
                Log.Info(string.Format("{0}() - GUIFormsMgr is DispatcherThread shutdown s_DispatcherThreadIsInitialized is False", MethodBase.GetCurrentMethod().Name));
            }
        }

    }
}
