//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
//
// UserWin satellite library | Author: Sergei Y.Kitáev
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
using System;
using System.Threading;
using System.ComponentModel;

using CommonHelpers;

namespace UserWin {

//**************************************************************************************************
/// <summary>
/// </summary>
public static partial class UXWMessageHelpers {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

[CLSCompliant(false)]
public const uint
   PM_NOREMOVE = 0x0000,
   PM_REMOVE   = 0x0001,
   PM_NOYIELD  = 0x0002;

//==================================================================================================

public static bool HasMessagesInQueue()
{
   return GetQueueStatus( ~0u );
}

[CLSCompliant(false)]
public static bool GetQueueStatus(uint flags)
{
   HProgram.VerifyInMainThread();
   return Win32.GetQueueStatus( flags ) != 0;
}

public static bool GetInputState()
{
   HProgram.VerifyInMainThread();
   return Win32.GetInputState();
}

//--------------------------------------------------------------------------------------------------

[CLSCompliant(false)]
public static Int32 GetMessage( out Win32_MSG msg, IntPtr hWnd,
                                uint wMsgFilterMin, uint wMsgFilterMax )
{
   HProgram.VerifyInMainThread();
   return Win32.GetMessage( out msg, hWnd, wMsgFilterMin, wMsgFilterMax );
}

[CLSCompliant(false)]
public static bool PeekMessage( out Win32_MSG msg, IntPtr hWnd,
                                uint wMsgFilterMin, uint wMsgFilterMax, uint wRemoveMsg )
{
   HProgram.VerifyInMainThread();
   return Win32.PeekMessage( out msg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg );
}

//--------------------------------------------------------------------------------------------------

[CLSCompliant(false)]
public static bool TranslateMessage([HIn]ref Win32_MSG msg)
{
   HProgram.VerifyInMainThread();
   return Win32.TranslateMessage(ref msg);
}

[CLSCompliant(false)]
public static IntPtr DispatchMessage([HIn]ref Win32_MSG msg)
{
   HProgram.VerifyInMainThread();
   return Win32.DispatchMessage(ref msg);
}

//--------------------------------------------------------------------------------------------------

[CLSCompliant(false)]
public static IntPtr SendMessage(IntPtr hWnd,uint msg,UIntPtr wParam,IntPtr lParam)
{
   HProgram.VerifyInMainThread();
   return Win32.SendMessage( hWnd, msg, wParam, lParam );
}

[CLSCompliant(false)]
public static bool PostMessage(IntPtr hWnd,uint msg,UIntPtr wParam,IntPtr lParam)
{
   HProgram.VerifyInMainThread();
   return Win32.PostMessage( hWnd, msg, wParam, lParam );
}

//--------------------------------------------------------------------------------------------------

/// <exception cref="Win32Exception" />
public static void WaitMessage()
{
   HProgram.VerifyInMainThread();
   if ( !Win32.WaitMessage() )
      throw HWin32Error.CreateExceptionFromLastError();
}

//==================================================================================================

public static void ProcessMessageQueueWithoutUIAccessAndClose()
{
   ProcessMessageQueueWithoutUIAccess
   (
      filterTimerMessage: true,
      filterCloseMessage: true
   );
}

public static void ProcessMessageQueueWithoutUIAccess( bool filterTimerMessage,
                                                       bool filterCloseMessage )
{
   HProgram.VerifyInMainThread();
   Win32_MSG msg;
   while ( PeekMessage( out msg, IntPtr.Zero, 0, 0, PM_REMOVE ) )
      if (!( msg.message == Win32.WM_TIMER && filterTimerMessage ||
             msg.message == Win32.WM_CLOSE && filterCloseMessage ||
             UXWMInputHelpers.IsInputMessage( msg.message ) ))
         DispatchMessage( ref msg );
}

//--------------------------------------------------------------------------------------------------

public static void ProcessMessageQueue()
{
   HProgram.VerifyInMainThread();
   Win32_MSG msg;
   while ( PeekMessage( out msg, IntPtr.Zero, 0, 0, PM_REMOVE ) )
   {
      TranslateMessage( ref msg );
      DispatchMessage( ref msg );
   }
}

public static void ProcessMessageQueueWhile(HWhileCallback whileCondition)
{
   HProgram.VerifyInMainThread();
   Win32_MSG msg;
   while ( whileCondition() )
      if ( PeekMessage( out msg, IntPtr.Zero, 0, 0, PM_REMOVE ) )
      {
         TranslateMessage( ref msg );
         DispatchMessage( ref msg );
      }
      else
         Thread.Sleep( 1 );
}

//==================================================================================================

static UXWMessageHelpers()
{
   UserWin_Library.Access();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // UXWMessageHelpers
//**************************************************************************************************

} // UserWin
