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

using System.Windows;
using System.Windows.Input;

using CommonHelpers;

namespace UserWin {

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

public static event Action
   BeforeShowHandler,
   AfterShowHandler;

public static UXShowMessageBoxCallback ShowMessageBoxCallback
{
   get { return _ShowMessageBoxCallback_; }
   set { _ShowMessageBoxCallback_ = value; }
}

public static UXGetMessageBoxOwnerWindowCallback GetAppropriateOwnerWindowCallback
{
   get { return _GetAppropriateOwnerWindowCallback_; }
   set { _GetAppropriateOwnerWindowCallback_ = value; }
}

[DefaultValue(_YesNoDialogDefaultIconDefault_)]
public static MessageBoxImage YesNoDialogDefaultIcon
{
   get { return _YesNoDialogDefaultIcon_; }
   set { _YesNoDialogDefaultIcon_ = value; }
}
[DefaultValue(_YesNoCancelDialogDefaultIconDefault_)]
public static MessageBoxImage YesNoCancelDialogDefaultIcon
{
   get { return _YesNoCancelDialogDefaultIcon_; }
   set { _YesNoCancelDialogDefaultIcon_ = value; }
}

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

[DefaultValue(null)]
public static string CaptionFormatString
{
   get { return _CaptionFormatString_; }
   set { _CaptionFormatString_ = value; }
}

[DefaultValue(_UseBeeperAccompanimentDefault_)]
public static bool UseBeeperAccompaniment
{
   get { return _UseBeeperAccompaniment_; }
   set { _UseBeeperAccompaniment_ = value; }
}

[DefaultValue(_ProcessWin32MessageQueueWithoutInputBeforeShowDefault_)]
public static bool ProcessWin32MessageQueueWithoutInputBeforeShow
{
   get { return _ProcessWin32MessageQueueWithoutInputBeforeShow_; }
   set { _ProcessWin32MessageQueueWithoutInputBeforeShow_ = value; }
}

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

public static MessageBoxResult DefaultResultFromButton(MessageBoxButton button)
{
   switch (button)
   {
   case MessageBoxButton.OK         : return MessageBoxResult.OK;
   case MessageBoxButton.OKCancel   : return MessageBoxResult.OK;
   case MessageBoxButton.YesNo      : return MessageBoxResult.Yes;
   case MessageBoxButton.YesNoCancel: return MessageBoxResult.Yes;
   }
   return MessageBoxResult.None;
}

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

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

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

static async Task<MessageBoxResult> DoShowMessage(
   [HOptional] UXShowMessageExtraInfo extraInfo,
   Window owner, string text, [HOptional] string caption,
   MessageBoxButton button, MessageBoxImage icon,
   MessageBoxResult defaultResult )
{
   HProgram.VerifyInMainThread();

   var sound = HSounds.Default;
   object data = null;
   var options = MessageBoxOptions.None;
   Exception e = null;

   if (extraInfo!=null)
   {
      sound = extraInfo.Sound;
      data = extraInfo.Data;
      options = extraInfo.Options;
      e = extraInfo.Exception;
   }

   Action handler = BeforeShowHandler;

   if ( handler != null ) handler();

   string
      captionFormatString = CaptionFormatString,
      title = caption != null ?
      captionFormatString != null ?
         string.Format( captionFormatString, caption ) :
         caption :
      UXApplication.Title;

   if ( sound == HSounds.Default )
      if ( icon == MessageBoxImage.Information )
         sound = HSounds.Information;
      else
      if ( icon == MessageBoxImage.Error )
         sound = HSounds.Error;
      else
      if ( icon == MessageBoxImage.Warning )
         sound = HSounds.Warning;
      else
      if ( icon == MessageBoxImage.Exclamation )
         sound = HSounds.Exclamation;
      else
      if ( icon == MessageBoxImage.Question )
         sound = HSounds.Question;
      else
         sound = HSounds.None;

   bool
      useBeeperAccompaniment = UseBeeperAccompaniment,
      useSound = useBeeperAccompaniment && sound!=HSounds.None && !HSound.IsMute;

   Cursor savedCursor = UXCursor.Current;

   if ( useSound && ( !HSound.IsInitialized ||
                      useBeeperAccompaniment && HBeeper.IsPlaybackActive ) )
      UXCursor.SetWait();

   if ( ProcessWin32MessageQueueWithoutInputBeforeShow )
      UXWMInputHelpers.ProcessMessageQueueWithoutInput();

   UHWndHelpers.TryReleaseCapture();

   var showMessageBoxCallback = ShowMessageBoxCallback;
   var rslt = await Task.Run<MessageBoxResult>(delegate{
      return UXDispatcher.Synchronize<MessageBoxResult>(delegate{
         if ( useSound )
         {
            Console.Beep( 37, 1 );
            HSound.Play( sound );
         }
         UXCursor.Reset();
         return showMessageBoxCallback != null ?
            showMessageBoxCallback( data, options,
               owner, text, e, title, button, icon, defaultResult ) :
            owner != null ?
               MessageBox.Show( owner, text, title, button, icon, defaultResult, options ) :
               MessageBox.Show( text, title, button, icon, defaultResult, options );
      });
   });

   if (useSound) HSound.Abort();

   UXCursor.Override( savedCursor );

   handler = AfterShowHandler;
   if ( handler != null ) handler();

   return rslt;
}

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

public static Window GetAppropriateOwnerWindow()
{
   HProgram.VerifyInMainThread();
   var callback = GetAppropriateOwnerWindowCallback;
   return callback!=null ? callback() :
      UXApplication.AnchorWindow ?? UXApplication.MainWindow;
}

public static Window GetAppropriateOwnerWindow([HOptional] Window owner)
{
   HProgram.VerifyInMainThread();
   return owner ?? GetAppropriateOwnerWindow();
}

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

const bool
   _UseBeeperAccompanimentDefault_ = true,
   _ProcessWin32MessageQueueWithoutInputBeforeShowDefault_ = false;
const MessageBoxImage
   _YesNoDialogDefaultIconDefault_ = MessageBoxImage.Exclamation;
const MessageBoxImage
   _YesNoCancelDialogDefaultIconDefault_ = MessageBoxImage.Exclamation;

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

static volatile UXShowMessageBoxCallback
   _ShowMessageBoxCallback_;
static volatile UXGetMessageBoxOwnerWindowCallback
   _GetAppropriateOwnerWindowCallback_;

static volatile MessageBoxImage
   _YesNoDialogDefaultIcon_ = _YesNoDialogDefaultIconDefault_,
   _YesNoCancelDialogDefaultIcon_ = _YesNoCancelDialogDefaultIconDefault_;

static volatile string
   _CaptionFormatString_;
static volatile bool
   _UseBeeperAccompaniment_ = _UseBeeperAccompanimentDefault_,
   _ProcessWin32MessageQueueWithoutInputBeforeShow_ =
      _ProcessWin32MessageQueueWithoutInputBeforeShowDefault_;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // UXMessageBox
//**************************************************************************************************

} // UserWin
