//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
//
// UserWin satellite library | Author: Sergei Y.Kitáev
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
using System;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Security.Permissions;

using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;

using CommonHelpers;

namespace UserWin {

//**************************************************************************************************
/// <summary>
/// </summary>
[SecurityPermission(SecurityAction.LinkDemand,Unrestricted=true)]
public partial class UXWindow: Window {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

public double Right
   { get { return GetRight(this); } }

public double Bottom
   { get { return GetBottom(this); } }

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

public Rect WindowRect
   { get { return GetWindowRect(this); } }

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

public IntPtr Handle
   { get { return GetHandle(this); } }

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

[TypeConverter(typeof(DialogResultConverter))]
public new bool? DialogResult
{
   get { return GetDialogResult(this); }
   set { SetDialogResult(this,value); }
}

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

[DefaultValue(_SynchronizeIsBusyWithApplicationDefault_)]
public bool SynchronizeIsBusyWithApplication
{
   get { return GetSynchronizeIsBusyWithApplication(this); }
   set { SetSynchronizeIsBusyWithApplication(this,value);  }
}

[DefaultValue(_CanCloseBusyDefault_)]
public bool CanCloseBusy
{
   get { return GetCanCloseBusy(this); }
   set { SetCanCloseBusy(this,value);  }
}

[DefaultValue(_CanCloseDisabledDefault_)]
public bool CanCloseDisabled
{
   get { return GetCanCloseDisabled(this); }
   set { SetCanCloseDisabled(this,value);  }
}

[DefaultValue(_BlockKeyboardInputWhenBusyDefault_)]
public bool BlockKeyboardInputWhenBusy
{
   get { return GetBlockKeyboardInputWhenBusy(this); }
   set { SetBlockKeyboardInputWhenBusy(this,value);  }
}

[DefaultValue(_BlockMouseInputWhenBusyDefault_)]
public bool BlockMouseInputWhenBusy
{
   get { return GetBlockMouseInputWhenBusy(this); }
   set { SetBlockMouseInputWhenBusy(this,value);  }
}

[DefaultValue(_FilterMainClientWMInputWhenBusyDefault_)]
public bool FilterMainClientWMInputWhenBusy
{
   get { return GetFilterMainClientWMInputWhenBusy(this); }
   set { SetFilterMainClientWMInputWhenBusy(this,value);  }
}

[DefaultValue(_ApplyWaitCursorWhenBusyDefault_)]
public bool ApplyWaitCursorWhenBusy
{
   get { return GetApplyWaitCursorWhenBusy(this); }
   set { SetApplyWaitCursorWhenBusy(this,value);  }
}
/*
[DefaultValue(_GlassEffectDefault_)]
public bool GlassEffect
{
   get { return GetGlassEffect(this); }
   set { SetGlassEffect(this,value);  }
}

public bool IsGlassEffectActive
{
   get { return GetIsGlassEffectActive(this); }
   set { SetIsGlassEffectActive(this,value);  }
}
*/
[DefaultValue(_DragMoveBehaviourDefault_)]
public bool DragMoveBehaviour
{
   get { return GetDragMoveBehaviour(this); }
   set { SetDragMoveBehaviour(this,value);  }
}

[DefaultValue(_SetsAnchorWindowOnActivationDefault_)]
public bool SetsAnchorWindowOnActivation
{
   get { return GetSetsAnchorWindowOnActivation(this); }
   set { SetSetsAnchorWindowOnActivation(this,value);  }
}

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

public bool IsBusy
{
   get { return GetIsBusy(this); }
   set { SetIsBusy(this,value);  }
}

public bool CloseDemand
{
   get { return GetCloseDemand(this); }
}

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

public bool CanClose
{
   get { return DetectCanClose( this ); }
}

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

public event RoutedPropertyChangedEventHandler<bool> IsBusyChanged
{
   add { AddHandler( IsBusyChangedEvent, value ); }
   remove { RemoveHandler( IsBusyChangedEvent, value ); }
}

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

public void Center()
{
   CenterBy( null );
}

public void CenterBy(UIElement centerByElement)
{
   double x, y, w, h;

   if ( centerByElement != null )
   {
      Point leftTop = centerByElement.PointToScreen( new Point() );

      w = (double)centerByElement.GetValue( Canvas.ActualWidthProperty  );
      h = (double)centerByElement.GetValue( Canvas.ActualHeightProperty );
      x = leftTop.X + ( w - ActualWidth ) / 2;
      y = leftTop.Y + ( h - ActualHeight ) / 2;
   }
   else
   {
      Rect wa = SystemParameters.WorkArea;
      x = wa.Left; y = wa.Top;
      w = wa.Width; h = wa.Height;
   }

   Left = Math.Max( Math.Min( x, SystemParameters.WorkArea.Right - ActualWidth ),
                    SystemParameters.WorkArea.Left );
   Top = Math.Max( Math.Min( y, SystemParameters.WorkArea.Bottom - ActualHeight ),
                   SystemParameters.WorkArea.Top );
}

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

public void SetPosition(double left,double top)
{
   SetPosition( this, left, top );
}

public void SetPositionAndSize(double left,double top,double width,double height)
{
   SetPositionAndSize( this, left, top, width, height );
}

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

public new void Close()
{
   UXWindow.Close( this );
}

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

public new bool? ShowDialog()
{
   return ShowDialog( this );
}
public bool? ShowDialog(bool saveCursor)
{
   return ShowDialog( this, saveCursor );
}

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

public bool? ShowDialogWithOwner([HOptional] Window owner)
{
   return ShowDialogWithOwner( this, owner );
}
public bool? ShowDialogWithOwner([HOptional] Window owner,bool saveCursor)
{
   return ShowDialogWithOwner( this, owner, saveCursor );
}

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

public bool? ShowDialogByMainForm()
{
   return ShowDialogByMainForm( this );
}
public bool? ShowDialogByMainForm(bool saveCursor)
{
   return ShowDialogByMainForm( this, saveCursor );
}

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

public void Restore()
{
   Restore( this );
}

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

public void TryFitIntoWorkArea()
{
   TryFitIntoWorkArea( this );
}

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

public bool BringToForeground()
{
   return BringToForeground( this );
}

public bool BringToForeground(out HOperationFailedException error)
{
   return BringToForeground( this, out error );
}

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

protected override void OnInitialized(EventArgs e)
{
   base.OnInitialized( e );

   if ( !DesignerProperties.GetIsInDesignMode( this ) )
   {
      Loaded += Window_Loaded;
      IsEnabledChanged += Window_IsEnabledChanged;
      IsBusyChanged += Window_IsBusyChanged;
   }
}

protected override void OnSourceInitialized(EventArgs e)
{
   base.OnSourceInitialized( e );
/*
   if (GlassEffect)
      ApplyGlassEffect(this);
*/
   var hwndSource = GetHwndSource( this);
   if ( hwndSource != null )
      hwndSource.AddHook( new HwndSourceHook( HwndSourceHookRoutine ) );
}

protected virtual void OnIsBusyChanged(RoutedPropertyChangedEventArgs<bool> args)
{
   RaiseEvent( args );
   if ( !args.Handled && ApplyWaitCursorWhenBusy )
      Cursor = args.NewValue ? Cursors.Wait : null;
}
/*
/// <exception cref="HOperationFailedException" />
protected virtual void OnIsGlassEffectChanged(RoutedPropertyChangedEventArgs<bool> args)
{
   if ( IsInitialized )
      throw new HOperationFailedException(
         "\"GlassEffect\" property can not be changed after initialization of window." );
}
*/
protected override void OnActivated(EventArgs e)
{
   if ( SetsAnchorWindowOnActivation )
      UXApplication.AnchorWindow = this;
   base.OnActivated( e );
   UXApplication.RaiseWindowActivated( this );
}

protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
   base.OnMouseLeftButtonDown( e );
   if ( !e.Handled && DragMoveBehaviour && e.Source==this )
      DragMove();
}

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

void Window_Loaded(object sender,RoutedEventArgs e)
{
   Loaded -= Window_Loaded;
   if ( SynchronizeIsBusyWithApplication )
      IsBusy = UXApplication.IsBusy;
}

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

IntPtr HwndSourceHookRoutine(IntPtr hwnd,int msg,IntPtr wParam,IntPtr lParam,ref bool handled)
{
   uint message = (uint)msg;
   if ( msg==Win32.WM_SYSCOMMAND && (uint)wParam==Win32.SC_CLOSE )
   {
      if ( IsBusy || !IsEnabled )
      {
         HSound.PlayDisabled();
         handled = true;
      }
      return IntPtr.Zero;
   }
   if ( IsBusy && FilterMainClientWMInputWhenBusy &&
        UXWMInputHelpers.IsClientInputMessage( message ) &&
        message != Win32.WM_MOUSEMOVE )
   {
      handled = true;
      return IntPtr.Zero;
   }
/*
   if ( msg == Win32.WM_DWMCOMPOSITIONCHANGED )
   {
      var window = FromHandle( hwnd );
      if ( GetGlassEffect( window ) )
         if ( IsCompositionEnabled )
            ApplyGlassEffect( window );
         else
         {
            window.Background = GetPreGlassEffectBackground( window ) ?? SystemColors.WindowBrush;
            SetIsGlassEffectActive( window, false );
         }
      handled = true;
      return IntPtr.Zero;
   }
*/
   return IntPtr.Zero;
}

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

const bool
   _SynchronizeIsBusyWithApplicationDefault_ = true,
   _CanCloseBusyDefault_                     = false,
   _CanCloseDisabledDefault_                 = false,
   _BlockKeyboardInputWhenBusyDefault_       = true,
   _BlockMouseInputWhenBusyDefault_          = true,
   _FilterMainClientWMInputWhenBusyDefault_  = true,
   _ApplyWaitCursorWhenBusyDefault_          = false,
// _GlassEffectDefault_                      = false,
   _DragMoveBehaviourDefault_                = false,
   _SetsAnchorWindowOnActivationDefault_     = true;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // UXWindow
//**************************************************************************************************

} // UserWin
