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

using System.Windows;
using System.Windows.Media;

using CommonHelpers;

namespace UserWin {

//**************************************************************************************************
/// <summary>
/// </summary>
public delegate bool HVisualObjectPredicate(DependencyObject visualObject);
//**************************************************************************************************


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

public static DependencyObject FindAncestor( DependencyObject descendantObject,
                                             HVisualObjectPredicate predicate )
{
   HArgChecking.VerifyNotNulls( descendantObject, predicate );
   var parent = VisualTreeHelper.GetParent( descendantObject );
   return parent!=null ?
      predicate(parent) ? parent : FindAncestor( parent, predicate ) :
      null;
}

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

public static DependencyObject FindDescendantObject( DependencyObject parent,
                                                     HVisualObjectPredicate predicate )
{
   HArgChecking.VerifyNotNulls( parent, predicate );
   for (int i=0; i<VisualTreeHelper.GetChildrenCount( parent ); i++)
   {
      var child = VisualTreeHelper.GetChild( parent, i );
//if (child is FrameworkContentElement)
//HDebug.PrintInformation( (child as FrameworkContentElement).Name );
      if (predicate( child ))
         return child;
      var descendantObject = FindDescendantObject( child, predicate );
      if (descendantObject!=null)
         return descendantObject;
   }
   return null;
}

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

public static T FindAncestor<T>(DependencyObject descendantObject) where T: DependencyObject
{
   return (T)FindAncestor( descendantObject,
      delegate (DependencyObject visualObject) {
         return visualObject is T; } );
}

public static T FindAncestor<T>( DependencyObject descendantObject,
                                 string name ) where T: FrameworkElement
{
   HArgChecking.VerifyNotNulls( descendantObject, name );
   return (T)FindAncestor( descendantObject,
      delegate (DependencyObject visualObject) {
         var element = visualObject as T;
         return element!=null && element.Name==name; } );
}

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

public static T FindDescendantObject<T>(DependencyObject parent) where T: DependencyObject
{
   return (T)FindDescendantObject( parent,
      delegate (DependencyObject visualObject) {
         return visualObject is T; } );
}

public static T FindDescendantObject<T>( DependencyObject parent,
                                         string name ) where T: FrameworkElement
{
   HArgChecking.VerifyNotNulls( parent, name );
   return (T)FindDescendantObject( parent,
      delegate (DependencyObject visualObject) {
         var element = visualObject as T;
         return element!=null && element.Name==name; } );
}

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

public static T StrictFindAncestor<T>(DependencyObject descendantObject) where T: DependencyObject
{
   var visualObject = FindAncestor<T>( descendantObject );
   if (visualObject==null)
      throw HOpFailedExceptionCreator.Create(
         "Visual ancestor of \"{0}\" type not found.", typeof(T) );
   return visualObject;
}

public static T StrictFindAncestor<T>( DependencyObject descendantObject,
                                       string name ) where T: FrameworkElement
{
   var visualObject = FindAncestor<T>( descendantObject, name );
   if (visualObject==null)
      throw HOpFailedExceptionCreator.Create(
         "Visual ancestor of \"{0}\" type not found by name: \"{1}\".",
         typeof(T), name );
   return visualObject;
}

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

public static T StrictFindDescendantObject<T>(DependencyObject parent) where T: DependencyObject
{
   var descendantObject = FindDescendantObject<T>( parent );
   if (descendantObject==null)
      throw HOpFailedExceptionCreator.Create(
         "Visual descendant object of \"{0}\" type not found.", typeof(T) );
   return descendantObject;
}

public static T StrictFindDescendantObject<T>( DependencyObject parent,
                                               string name ) where T: FrameworkElement
{
   var descendantObject = FindDescendantObject<T>( parent, name );
   if (descendantObject==null)
      throw HOpFailedExceptionCreator.Create(
         "Visual descendant object of \"{0}\" type not found by name: \"{1}\".",
         typeof(T), name );
   return descendantObject;
}

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

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

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // UXVisualTreeHelper
//**************************************************************************************************

} // UserWin
