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

using WF = System.Windows.Forms;
using DRW = System.Drawing;

using CommonHelpers;

namespace WFX {

//**************************************************************************************************
/// <summary>
/// </summary>
public partial class HotLabel: WF.Label {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

public new DRW.Color DefaultForeColor
{
   get { return DRW.Color.White; }
}

public new DRW.Color DefaultBackColor
{
   get { return DRW.Color.CornflowerBlue; }
}

[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public DRW.Color HighlightingForeColorDefault
{
   get { return DRW.Color.DimGray; }
}

[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public DRW.Color HighlightingBackColorDefault
{
   get { return DRW.Color.Aqua; }
}

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

[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public DRW.Color BlockingForegroundColorDefault
{
   get { return DRW.Color.DimGray; }
}

[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public DRW.Color BlockingBackgroundColorDefault
{
   get { return DRW.Color.Silver; }
}

[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public DRW.Color BlockingHighlightingForeColorDefault
{
   get { return DRW.Color.DarkGray; }
}

[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public DRW.Color BlockingHighlightingBackColorDefault
{
   get { return DRW.Color.Silver; }
}

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

[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public DRW.Color ForegroundColor
{
   get { return _ForegroundColor_; }
   set { _ForegroundColor_ = value; UpdateColors(); }
}

[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public DRW.Color BackgroundColor
{
   get { return _BackgroundColor_; }
   set { _BackgroundColor_ = value; UpdateColors(); }
}

[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public DRW.Color HighlightingForeColor
{
   get { return _HighlightingForeColor_; }
   set { _HighlightingForeColor_ = value; UpdateColors(); }
}

[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public DRW.Color HighlightingBackColor
{
   get { return _HighlightingBackColor_; }
   set { _HighlightingBackColor_ = value; UpdateColors(); }
}

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

[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public DRW.Color BlockingForegroundColor
{
   get { return _BlockingForegroundColor_; }
   set { _BlockingForegroundColor_ = value; UpdateColors(); }
}

[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public DRW.Color BlockingBackgroundColor
{
   get { return _BlockingBackgroundColor_; }
   set { _BlockingBackgroundColor_ = value; UpdateColors(); }
}

[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public DRW.Color BlockingHighlightingForeColor
{
   get { return _BlockingHighlightingForeColor_; }
   set { _BlockingHighlightingForeColor_ = value; UpdateColors(); }
}

[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public DRW.Color BlockingHighlightingBackColor
{
   get { return _BlockingHighlightingBackColor_; }
   set { _BlockingHighlightingBackColor_ = value; UpdateColors(); }
}

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

[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool IsBlocked
{
   get { return _IsBlocked_; }
   set { _IsBlocked_ = value; UpdateColors(); }
}

[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool IsHighlighted { get; private set; }

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

public HotLabel()
{
   _ForegroundColor_ = DefaultForeColor;
   _BackgroundColor_ = DefaultBackColor;
   _HighlightingForeColor_ = HighlightingForeColorDefault;
   _HighlightingBackColor_ = HighlightingBackColorDefault;
   _BlockingForegroundColor_ = BlockingForegroundColorDefault;
   _BlockingBackgroundColor_ = BlockingBackgroundColorDefault;
   _BlockingHighlightingForeColor_ = BlockingHighlightingForeColorDefault;
   _BlockingHighlightingBackColor_ = BlockingHighlightingBackColorDefault;
   UpdateColors();
   if ( !DesignMode )
   lock ( _TimerSyncRoot_ )
   {
      var timer = _Timer_;
      bool timerInitialization = timer == null;
      if ( timerInitialization ) timer = new WF.Timer() { Interval = 300 };
      timer.Tick += TimerTick_Handler;
      if ( timerInitialization ) _Timer_ = timer;
      _TimerRefCount_++;
      if ( timerInitialization ) timer.Enabled = true;
   }
}

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

public void UpdateHighlighted()
{
   UpdateHighlighted( true );
}

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

protected override void OnMouseEnter(EventArgs e)
{
   base.OnMouseEnter( e ); UpdateHighlighted();
}

protected override void OnMouseHover(EventArgs e)
{
   base.OnMouseHover( e ); UpdateHighlighted();
}

protected override void OnMouseLeave(EventArgs e)
{
   base.OnMouseLeave( e ); UpdateHighlighted( false );
}

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

protected override void OnClick(EventArgs e)
{}

protected override void OnMouseClick(WF.MouseEventArgs e)
{
   UpdateHighlighted();
   if ( IsHighlighted )
      if ( IsBlocked )
         PlayBlockedSoundSignal();
      else
         base.OnClick( e );
}

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

protected override void OnVisibleChanged(EventArgs e)
{
   base.OnVisibleChanged( e ); UpdateHighlighted();
}

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

protected virtual void PlayBlockedSoundSignal()
{
   HSound.PlayDisabled();
}

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

protected override void Dispose(bool disposing)
{
   if ( _DisposeFlag_ ) return;
   _DisposeFlag_ = true;
   lock ( _TimerSyncRoot_ )
   if ( _Timer_ != null  )
   {
      _Timer_.Tick -= TimerTick_Handler;
      if ( --_TimerRefCount_ == 0 )
         HDisposable.Dispose(ref _Timer_);
   }
   base.Dispose( disposing );
}

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

void UpdateColors()
{
   var color = IsBlocked ?
      IsHighlighted ? BlockingHighlightingForeColor : BlockingForegroundColor :
      IsHighlighted ? HighlightingForeColor : ForegroundColor;
   if ( color != ForeColor ) ForeColor = color;
   color = IsBlocked ?
      IsHighlighted ? BlockingHighlightingBackColor : BlockingBackgroundColor :
      IsHighlighted ? HighlightingBackColor : BackgroundColor;
   if ( color != BackColor ) BackColor = color;
   Update();
}

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

void UpdateHighlighted(bool canBeHighlighted)
{
   if ( _DisposeFlag_ || DesignMode ) return;
   if ( canBeHighlighted )
   {
      if ( !Visible || Application.IsBusy )
         canBeHighlighted = false;
      else
      {
         var form = TopLevelControl as WF.Form;
         if ( form != null )
         {
            IntPtr hForm = form!=null ? form.Handle : IntPtr.Zero;
            if ( hForm == IntPtr.Zero ) return;
            if ( Win32.IsWindowEnabled( hForm ) )
            {
               Win32.POINT cursorPoint;
               if ( !Win32.GetCursorPos(out cursorPoint) ) return;
               canBeHighlighted &= Win32.WindowFromPoint( cursorPoint ) == Handle;
            }
            else
               canBeHighlighted = false;
         }
      }
   }
   canBeHighlighted &= HOps.IsOneOf( Mouse.GetCapture(), IntPtr.Zero, Handle );
   if ( WF.Cursor.Current != WF.Cursors.WaitCursor )
      Cursor = canBeHighlighted ? WF.Cursors.Hand : WF.Cursors.Default;
   var wasHighlighted = IsHighlighted;
   IsHighlighted = canBeHighlighted && Control.IsMouseWithin( this );
   if ( IsHighlighted != wasHighlighted )
      UpdateColors();
}

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

void TimerTick_Handler(object sender,EventArgs e)
{
   UpdateHighlighted();
}

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

static readonly object
   _TimerSyncRoot_ = new object();
static WF.Timer
   _Timer_;
static int
   _TimerRefCount_;

DRW.Color
   _ForegroundColor_,
   _BackgroundColor_,
   _HighlightingForeColor_,
   _HighlightingBackColor_,
   _BlockingForegroundColor_,
   _BlockingBackgroundColor_,
   _BlockingHighlightingForeColor_,
   _BlockingHighlightingBackColor_;
bool
   _IsBlocked_;
volatile bool
   _DisposeFlag_;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // HotLabel
//**************************************************************************************************

} // WFX
