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

using WF = System.Windows.Forms;

using CommonHelpers;

namespace WFX {

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

public static event Action
   BeforeShowHandler,
   AfterShowHandler;

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

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

[DefaultValue(_YesNoDialogDefaultIconDefault_)]
public static WF.MessageBoxIcon YesNoDialogDefaultIcon
{
   get { return _YesNoDialogDefaultIcon_; }
   set { _YesNoDialogDefaultIcon_ = value; }
}
[DefaultValue(_YesNoCancelDialogDefaultIconDefault_)]
public static WF.MessageBoxIcon 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; }
}

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

/// <exception cref="ArgumentException" />
public static WF.DialogResult DefaultResultFromButtons(WF.MessageBoxButtons buttons)
{
   switch (buttons)
   {
   case WF.MessageBoxButtons.OK         : return WF.DialogResult.OK;
   case WF.MessageBoxButtons.OKCancel   : return WF.DialogResult.OK;
   case WF.MessageBoxButtons.YesNo      : return WF.DialogResult.Yes;
   case WF.MessageBoxButtons.YesNoCancel: return WF.DialogResult.Yes;
   }
   throw new ArgumentException();
}

/// <exception cref="ArgumentException" />
public static WF.MessageBoxDefaultButton DefaultResultToButton( WF.MessageBoxButtons buttons,
                                                                WF.DialogResult defaultResult )
{
   switch (buttons)
   {
   case WF.MessageBoxButtons.OK:
      if ( defaultResult == WF.DialogResult.OK )
         return WF.MessageBoxDefaultButton.Button1;
      break;
   case WF.MessageBoxButtons.OKCancel:
      if ( defaultResult == WF.DialogResult.OK )
         return WF.MessageBoxDefaultButton.Button1;
      if ( defaultResult == WF.DialogResult.Cancel )
         return WF.MessageBoxDefaultButton.Button2;
      break;
   case WF.MessageBoxButtons.YesNo:
      if ( defaultResult == WF.DialogResult.Yes )
         return WF.MessageBoxDefaultButton.Button1;
      if ( defaultResult == WF.DialogResult.No )
         return WF.MessageBoxDefaultButton.Button2;
      break;
   case WF.MessageBoxButtons.YesNoCancel:
      if ( defaultResult == WF.DialogResult.Yes )
         return WF.MessageBoxDefaultButton.Button1;
      if ( defaultResult == WF.DialogResult.No )
         return WF.MessageBoxDefaultButton.Button2;
      if ( defaultResult == WF.DialogResult.Cancel )
         return WF.MessageBoxDefaultButton.Button3;
      break;
   }
   throw new ArgumentException();
}

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

static MessageBox()
{
   WFX_Library.Access();
}

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

static WF.DialogResult DoShowMessage( [HOptional] ShowMessageExtraInfo extraInfo,
                                      [HOptional] WF.IWin32Window owner,
                                      string text, [HOptional] string caption,
                                      WF.MessageBoxButtons buttons, WF.MessageBoxIcon icon,
                                      WF.DialogResult defaultResult )
{
   var sound = HSounds.Default;
   object data = null;
   WF.MessageBoxOptions options = 0;
   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 :
         Application.Title;

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

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

   var savedCursor = WF.Cursor.Current;

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

   if (useSound)
   {
      Console.Beep(37,1);
      HSound.Play( sound );
   }

   if ( ProcessWin32MessageQueueWithoutInputBeforeShow )
      Input.ProcessMessageQueueWithoutInput();

   var showMessageBoxCallback = ShowMessageBoxCallback;
   var defaultButton = DefaultResultToButton( buttons, defaultResult );

   Cursor.Reset();

   WF.DialogResult result;
   if ( showMessageBoxCallback != null )
      result = showMessageBoxCallback( data, options,
         owner, text, e, title, buttons, icon, defaultButton );
   else
   {
      owner = GetAppropriateOwnerWindow( owner );
      result = owner != null ?
         WF.MessageBox.Show( owner, text, title, buttons, icon, defaultButton, options ) :
         WF.MessageBox.Show( text, title, buttons, icon, defaultButton, options );
   }

   if (useSound) HSound.Abort();

   Application.UpdateOpenForms();

   Cursor.Override( savedCursor );

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

   return result;
}

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

public static WF.IWin32Window GetAppropriateOwnerWindow()
{
   HProgram.VerifyInMainThread();
   var callback = GetAppropriateOwnerWindowCallback;
   return callback!=null ? callback() : Application.AnchorWindow;
}

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

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

const bool
   _UseBeeperAccompanimentDefault_ = true,
   _ProcessWin32MessageQueueWithoutInputBeforeShowDefault_ = true;
const WF.MessageBoxIcon
   _YesNoDialogDefaultIconDefault_ = WF.MessageBoxIcon.Exclamation;
const WF.MessageBoxIcon
   _YesNoCancelDialogDefaultIconDefault_ = WF.MessageBoxIcon.Exclamation;

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

static volatile ShowMessageBoxCallback
   _ShowMessageBoxCallback_;
static GetMessageBoxOwnerWindowCallback
   _GetAppropriateOwnerWindowCallback_;

static volatile WF.MessageBoxIcon
   _YesNoDialogDefaultIcon_ = _YesNoDialogDefaultIconDefault_,
   _YesNoCancelDialogDefaultIcon_ = _YesNoCancelDialogDefaultIconDefault_;

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

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // MessageBox
//**************************************************************************************************

} // WFX
