
using Godot;
using Rokojori;
using System.Collections.Generic;
using System.Linq;

namespace Rokojori
{ 

  [Tool]
  [GlobalClass] 
  public partial class UIStyle:Resource, UIStylePropertyContainer
  {
    [ExportGroup( "Layout" )]
    [Export]
    public UILayout layout;        

    [Export]
    public UINumber horizontalAlignment;
    [Export]
    public UINumber verticalAlignment;
    [Export]
    public UINumber verticalPlacement;

    [Export]
    public UINumber elementSpacing;
    [Export]
    public UINumber lineSpacing;

    
    [ExportGroup( "Size & Margins" )]
    [Export]
    public UINumber width;
    [Export]
    public UINumber height;


    [Export] 
    public UINumber margin;

    [Export] 
    public UINumber marginLeft;
    [Export] 
    public UINumber marginTop;
    [Export] 
    public UINumber marginRight;
    [Export] 
    public UINumber marginBottom;

    [ExportGroup( "Font" )]
    [Export]
    public Font font;
    [Export]
    public UINumber fontSize;
    [Export]
    public UIColor fontColor;

    [Export]
    public UINumber outlineSize;
    [Export]
    public UIColor outlineColor;

    [Export]
    public UINumber shadowSize;
    [Export]
    public UIColor shadowColor;

    [Export]
    public UINumber shadowOffsetX;
    [Export]
    public UINumber shadowOffsetY;

    [ExportGroup( "Position" )]
    [Export]
    public UIPosition position;
    [Export]
    public UILineWrap lineWrap;
    [Export]
    public UINumber left;
    [Export]
    public UINumber top;
    [Export]
    public UINumber right;
    [Export]
    public UINumber bottom;

    [ExportGroup("Rotation & Scale")]
    [Export]
    public UINumber pivotX;
    [Export]
    public UINumber pivotY;

    [Export]
    public UINumber rotation;

    [Export]
    public UINumber scale;

    [Export]
    public UINumber scaleX;
    [Export]
    public UINumber scaleY;

    [ExportGroup( "Modulation" )]
    [Export]
    public UIColor modulationColor;
    [Export]
    public UIColor selfModulationColor;

    [ExportGroup( "Shader Properties" )]
    [Export]
    public ShaderUIColor[] colorProperties = new ShaderUIColor[ 0 ];
    [Export]
    public ShaderUINumber[] numberProperties = new ShaderUINumber[ 0 ];

    

    public Font GetFont()
    {
      return font;
    }

    public List<ActiveStyleTransition<UIColor,ColorPropertyName>> GetActiveShaderUIColorTransitions()
    {
      return null;
    }
  
    public List<ActiveStyleTransition<UINumber,FloatPropertyName>> GetActiveShaderUINumberTransitions()
    {
      return null;
    }

    [ExportGroup("Transitions")]
    [Export]
    public TransitionSettingsAll transitionSettings;
    public TransitionSettingsAll GetTransitionSettingsAll()
    {
      return transitionSettings;
    }

    [Export]
    public UINumberTransition[] numberTransitions = new UINumberTransition[ 0 ];
    public UINumberTransition[] GetNumberTransitions()
    {
      return numberTransitions;
    }

    public List<ActiveStyleTransition<UINumber,UIStyleNumberPropertyAndName>> GetActiveUINumberTransitions()
    {
      return null;
    }

    
    [Export]
    public UIColorTransition[] colorTransitions = new UIColorTransition[ 0 ];
    public UIColorTransition[] GetColorTransitions()
    {
      return colorTransitions;
    }    
    
    public List<ActiveStyleTransition<UIColor,UIStyleColorPropertyAndName>> GetActiveUIColorTransitions()
    {
      return null;
    }


    [ExportGroup("Pointer")]
    [Export]
    public UICursor hoverCursor;


    [ExportGroup( "Selectors & Parent " )]
    
    [Export]
    public UISelectorStyle[] selectorStyles = [];

    [Export]
    public UIStyle parentStyle;

    // public UICursor GetOwnUICursor( Control control )
    // {
    //   if ( )
    // }

    public UICursor GetHoverCursor( UIStylePropertyContainer container )
    {
      for ( int i = 0; i < selectorStyles.Length; i++ )
      {
        if ( selectorStyles[ i ] == null  || selectorStyles[ i ].style == null )
        {
          continue;
        }

        if ( selectorStyles[ i ].selector == null || selectorStyles[ i ].selector.Selects( container ) )
        {
          var uiCursor = selectorStyles[ i ].style.GetHoverCursor( container );

          if ( uiCursor != null )
          {
            return uiCursor;
          }
        } 
      }

      return hoverCursor;
    }


    public static UICursor ResolveHoverCursor( Control control )
    {
      var container = control as UIStylePropertyContainer;

      var ownCursor = container.GetHoverCursor( container );

      if ( ownCursor != null )
      {
        return ownCursor;
      }

      var parentStyle = container.GetUIStyleParent();

      if ( parentStyle == null )
      {
        return null;
      }

      return parentStyle.GetHoverCursor( container );
    }

    public UIStyle GetUIStyleParent()
    {
      return parentStyle;
    }

    public void SetUIStyleParent( UIStyle uiStyle )
    {
      parentStyle = uiStyle;
    }
    
    public UIPosition GetUIPosition()
    {
      return position;
    }

    public UILineWrap GetUILineWrap()
    {
      return lineWrap;
    }

    public UILayout GetUILayout()
    {
      return layout;
    }

    public ShaderUIColor[] GetShaderUIColors()
    {
      return colorProperties;
    }

    public ShaderUINumber[] GetShaderUINumbers()
    {
      return numberProperties;
    }

    public UINumber GetUIStyleNumberProperty( UIStyleNumberProperty property, string shaderPropertyName, UIStylePropertyContainer source )
    {
      for ( int i = 0; i < selectorStyles.Length; i++ )
      {
        if ( selectorStyles[ i ] == null  || selectorStyles[ i ].style == null )
        {
          continue;
        }

        if ( selectorStyles[ i ].selector == null || selectorStyles[ i ].selector.Selects( source ) )
        {
          var selectedProperty =  selectorStyles[ i ].style.GetUIStyleNumberProperty( property, shaderPropertyName );

          if ( selectedProperty != null )
          {
            return selectedProperty;
          }
        } 
      }

      return GetUIStyleNumberProperty( property, shaderPropertyName );
    }

    public UINumber GetUIStyleNumberProperty( UIStyleNumberProperty property, string shaderPropertyName )
    {
      switch ( property )
      {
        case UIStyleNumberProperty.Left:   return left;
        case UIStyleNumberProperty.Right:  return right;
        case UIStyleNumberProperty.Top:    return top;
        case UIStyleNumberProperty.Bottom: return bottom;

        case UIStyleNumberProperty.HorizontalAlignment: return horizontalAlignment;
        case UIStyleNumberProperty.VerticalAlignment: return verticalAlignment;
        case UIStyleNumberProperty.VerticalPlacement: return verticalPlacement;
        case UIStyleNumberProperty.ElementSpacing: return elementSpacing;
        case UIStyleNumberProperty.LineSpacing:    return lineSpacing;


        case UIStyleNumberProperty.Width:  return width;
        case UIStyleNumberProperty.Height: return height;



        case UIStyleNumberProperty.Margin:       return margin;

        case UIStyleNumberProperty.MarginLeft:   return marginLeft;
        case UIStyleNumberProperty.MarginRight:  return marginRight;
        case UIStyleNumberProperty.MarginTop:    return marginTop;
        case UIStyleNumberProperty.MarginBottom: return marginBottom;

        case UIStyleNumberProperty.FontSize: return fontSize;
        case UIStyleNumberProperty.FontOutlineSize: return outlineSize;
        case UIStyleNumberProperty.FontShadowSize: return shadowSize;
        case UIStyleNumberProperty.FontShadowOffsetX: return shadowOffsetX;
        case UIStyleNumberProperty.FontShadowOffsetY: return shadowOffsetY;

        case UIStyleNumberProperty.PivotX:   return pivotX;
        case UIStyleNumberProperty.PivotY:   return pivotY;
        case UIStyleNumberProperty.Rotation: return rotation;

        case UIStyleNumberProperty.Scale:    return scale;
        case UIStyleNumberProperty.ScaleX:   return scaleX;
        case UIStyleNumberProperty.ScaleY:   return scaleY;
      }

      if ( UIStyleNumberProperty.FloatShaderProperty == property )
      {
        var numberProperty = numberProperties.Find( n => n.floatPropertyName.propertyName == shaderPropertyName );

        if ( numberProperty != null )
        {
          return numberProperty.number;
        }

      }

      return null;
    }

    public void SetUIStyleNumberProperty( UIStyleNumberProperty property, UINumber number )
    {
      switch ( property )
      {
        case UIStyleNumberProperty.Left:   { left = number; } break;
        case UIStyleNumberProperty.Right:  { right = number; } break;
        case UIStyleNumberProperty.Top:    { top = number; } break;
        case UIStyleNumberProperty.Bottom: { bottom = number; } break;

        case UIStyleNumberProperty.HorizontalAlignment: { horizontalAlignment = number; } break;
        case UIStyleNumberProperty.VerticalAlignment: { verticalAlignment = number; } break;
        case UIStyleNumberProperty.VerticalPlacement: { verticalPlacement = number; } break;
        case UIStyleNumberProperty.ElementSpacing: { elementSpacing = number; } break;
        case UIStyleNumberProperty.LineSpacing:    { lineSpacing = number; } break;


        case UIStyleNumberProperty.Width:  { width = number; } break;
        case UIStyleNumberProperty.Height: { height = number; } break;



        case UIStyleNumberProperty.Margin:       { margin = number; } break;

        case UIStyleNumberProperty.MarginLeft:   { marginLeft = number; } break;
        case UIStyleNumberProperty.MarginRight:  { marginRight = number; } break;
        case UIStyleNumberProperty.MarginTop:    { marginTop = number; } break;
        case UIStyleNumberProperty.MarginBottom: { marginBottom = number; } break;

        case UIStyleNumberProperty.FontSize: { fontSize = number; } break;
        case UIStyleNumberProperty.FontOutlineSize: { outlineSize = number; } break;
        case UIStyleNumberProperty.FontShadowSize: { shadowSize = number; } break;
        case UIStyleNumberProperty.FontShadowOffsetX: { shadowOffsetX = number; } break;
        case UIStyleNumberProperty.FontShadowOffsetY: { shadowOffsetY = number; } break;

        case UIStyleNumberProperty.PivotX:   { pivotX = number; } break;
        case UIStyleNumberProperty.PivotY:   { pivotY = number; } break;
        case UIStyleNumberProperty.Rotation: { rotation = number; } break;

        case UIStyleNumberProperty.Scale:    { scale = number; } break;
        case UIStyleNumberProperty.ScaleX:   { scaleX = number; } break;
        case UIStyleNumberProperty.ScaleY:   { scaleY = number; } break;
      }

    }

    public Vector2 GetUISize()
    {
      return new Vector2( 1, 1 );
    }

    public List<UISelectorFlag> GetUISelectorFlags()
    {
      return UISelectorFlag.NoFlags;
    }

    public List<UISelectorFlag> GetParentUISelectorFlags()
    {
      return UISelectorFlag.NoFlags;
    }

    public void AddUISelectorFlag( UISelectorFlag flag, string reference = "" )
    {}

    public void RemoveUISelectorFlag( UISelectorFlag flag, string reference = "" )
    {}

    public void UpdateParentUISelectorFlags()
    {}

    public UIColor GetUIStyleColorProperty( UIStyleColorProperty property, string shaderPropertyName, UIStylePropertyContainer source )
    {     

      for ( int i = 0; i < selectorStyles.Length; i++ )
      {
        if ( selectorStyles[ i ] == null  || selectorStyles[ i ].style == null )
        {
          continue;
        }

        if ( selectorStyles[ i ].selector == null || selectorStyles[ i ].selector.Selects( source ) )
        {
          var selectedProperty =  selectorStyles[ i ].style.GetUIStyleColorProperty( property, shaderPropertyName );

          if ( selectedProperty != null )
          {
            return selectedProperty;
          }
        } 
      }

      return GetUIStyleColorProperty( property, shaderPropertyName );
    }

    public UIColor GetUIStyleColorProperty( UIStyleColorProperty property, string shaderPropertyName )
    {
      switch ( property )
      {
        case UIStyleColorProperty.FontColor:            return fontColor;
        case UIStyleColorProperty.FontOutlineColor:     return outlineColor;
        case UIStyleColorProperty.FontShadowColor:      return shadowColor;
        case UIStyleColorProperty.ModulationColor:      return modulationColor;
        case UIStyleColorProperty.SelfModulationColor:  return selfModulationColor;
        case UIStyleColorProperty.ColorShaderProperty:
        {
          var shaderUIColor = Arrays.FindNonNull( colorProperties,
           c => 
           c.colorPropertyName?.propertyName == shaderPropertyName
          ); 

          return shaderUIColor != null ? shaderUIColor.color : null;
        }
      } 

      return null;
    }

    public static UINumber GetReferenceableNumberProperty( UIStylePropertyContainer container, 
    UIStyleNumberProperty property, string shaderPropertyName, UIStylePropertyContainer source )
    {
      if ( container == null )
      {
        return null;
      }

      var ownProperty = container.GetUIStyleNumberProperty( property, shaderPropertyName, source );

      if ( ownProperty != null )
      {
        return ownProperty;
      }

      var style = container.GetUIStyleParent();

      return GetReferenceableNumberProperty( style, property, shaderPropertyName, source );
    } 

     public static UIColor GetReferenceableColorProperty( UIStylePropertyContainer container, 
     UIStyleColorProperty property, string shaderPropertyName, UIStylePropertyContainer source )
    {
      if ( container == null )
      {
        return null;
      }

      var ownProperty = container.GetUIStyleColorProperty( property, shaderPropertyName, source );

      if ( ownProperty != null )
      {
        return ownProperty;
      }

      var style = container.GetUIStyleParent();

      return GetReferenceableColorProperty( style, property, shaderPropertyName, source );
    } 

    public static UINumberTransition GetTransition( UIStylePropertyContainer container, UIStyleNumberProperty property, string shaderPropertyName )
    {
      switch ( property )
      {
        case UIStyleNumberProperty.FontSize:
        case UIStyleNumberProperty.FontOutlineSize:
        case UIStyleNumberProperty.FontShadowSize:
        case UIStyleNumberProperty.FontShadowOffsetX:
        case UIStyleNumberProperty.FontShadowOffsetY:
        case UIStyleNumberProperty.FloatShaderProperty:
        {
          return _GetTransition( true, container, property, shaderPropertyName );
        }
      }

      return _GetTransition( false, container, property, shaderPropertyName);
    
    }

    static UINumberTransition _GetTransition( bool inheritable, UIStylePropertyContainer container, UIStyleNumberProperty property, string shaderPropertyName )
    {
      if ( container == null )
      {
        return null;
      }

      var transitions = container.GetNumberTransitions();

      var index = transitions == null ? -1 : Arrays.FindIndex( transitions, t => t != null && t.Matches( property, shaderPropertyName ) );

      if ( index != -1 )
      {
        return transitions[ index ];
      }      

      var styleParent = container.GetUIStyleParent();

      if ( styleParent != null )
      {
        var styleParentTransition = _GetTransition( false, styleParent, property, shaderPropertyName );

        if ( styleParentTransition != null )
        {
          return styleParentTransition;
        }
      }

      

      if ( ! ( container is Control ) || ! inheritable )
      {
        return null;
      }

      var control = container as Control;
      UINumberTransition parentTransition = null;

      NodesWalker.Get().GetInParents( control, 
        it => 
        {
          if ( ! ( it is UIStylePropertyContainer ) )
          {
            return false;
          }

          var container = (UIStylePropertyContainer) it;
          parentTransition = _GetTransition( true, container, property, shaderPropertyName );

          return parentTransition != null;
        }
      );

      return parentTransition; 

    }

    public static TransitionSettingsAll GetTransitionSettingsAll( UIStylePropertyContainer container )
    {
      if ( container == null )
      {
        return null;
      }

      var settings = container.GetTransitionSettingsAll();

      if ( settings != null )
      {
        return settings;
      }

      var styleParent = container.GetUIStyleParent();

      if ( styleParent == null )
      {
        return null;
      }

      return GetTransitionSettingsAll( styleParent );
    }
    

    /*public static TransitionSettings GetTransitionSettings( UIStylePropertyContainer container, FloatPropertyName floatProperty )
    {
      var transition = GetTransition( container, floatProperty );

      if ( transition != null && transition.settings != null )
      {
        return transition.settings;
      }

      var containerSettings = container.GetTransitionSettingsAll();

      if ( containerSettings != null )
      {
        return containerSettings;
      }

      var styleParent = container.GetUIStyleParent();

      if ( styleParent == null )
      {
        return null;
      }

      return GetTransitionSettings( styleParent, floatProperty );
    }
    */


    public static TransitionSettings GetTransitionSettings( UIStylePropertyContainer container, UIStyleColorProperty colorProperty, string shaderPropertyName )
    {
      var transition = GetTransition( container, colorProperty, shaderPropertyName );

      if ( transition != null && transition.settings != null )
      {
        return transition.settings;
      }

      var containerSettings = container.GetTransitionSettingsAll();

      if ( containerSettings != null )
      {
        return containerSettings;
      }

      var styleParent = container.GetUIStyleParent();

      if ( styleParent == null )
      {
        return null;
      }

      return GetTransitionSettings( styleParent, colorProperty, shaderPropertyName );
    }


    
    public static TransitionSettings GetTransitionSettings( UIStylePropertyContainer container, UIStyleNumberProperty numberProperty, string shaderPropertyName )
    {
      var transition = GetTransition( container, numberProperty, shaderPropertyName );

      if ( transition != null && transition.settings != null )
      {
        return transition.settings;
      }

      var containerSettings = container.GetTransitionSettingsAll();

      if ( containerSettings != null )
      {
        return containerSettings;
      }

      var styleParent = container.GetUIStyleParent();

      if ( styleParent == null )
      {
        return null;
      }

      return GetTransitionSettings( styleParent, numberProperty, shaderPropertyName );
    }

    public static UIColorTransition GetTransition( UIStylePropertyContainer container, UIStyleColorProperty property, string shaderPropertyName )
    {
      switch ( property )
      {
        case UIStyleColorProperty.FontColor:
        case UIStyleColorProperty.FontOutlineColor:
        case UIStyleColorProperty.FontShadowColor:
        case UIStyleColorProperty.ColorShaderProperty:
        {
          return _GetTransition( true, container, property, shaderPropertyName );
        }
      }

      return _GetTransition( false, container, property, shaderPropertyName );
    
    }

    public static Control debugInfo = null;

    static UIColorTransition _GetTransition( 
      bool inheritable, UIStylePropertyContainer container, 
      UIStyleColorProperty property, string shaderPropertyName 
    )
    {
      var transitions = container.GetColorTransitions();

      if ( debugInfo != null )
      {
        var length = transitions == null ? -1 : transitions.Length; 
        debugInfo.LogInfo( "Own transition:",  HierarchyName.OfAny( container ), " , ", length );

        if ( transitions != null )
        {
          debugInfo.LogInfo( transitions.Map( t => t.property ).ToList().Join( ", " ) );
        }
      }



      var transition = transitions.Find( t => t != null && t.Matches( property, shaderPropertyName ) );

      if ( transition != null )
      {
        return transition;
      }      

      var styleParent = container.GetUIStyleParent();

      if ( styleParent != null )
      {
        if ( debugInfo != null )
        {
          debugInfo.LogInfo( "Found Style Parent:",  HierarchyName.OfAny( container ), " , ", HierarchyName.OfAny( styleParent ) );
        }


        var styleParentTransition = _GetTransition( false, styleParent, property, shaderPropertyName );

        if ( styleParentTransition != null )
        {
          if ( debugInfo != null )
          {
            debugInfo.LogInfo( "Found Style Parent Transition:",  HierarchyName.OfAny( container ), " , ", HierarchyName.OfAny( styleParent ) );
          }

          return styleParentTransition;
        }
        else
        { 
           if ( debugInfo != null )
          {
            debugInfo.LogInfo( "No Style Parent Transition:",  HierarchyName.OfAny( container ), " , ", HierarchyName.OfAny( styleParent ) );
          }
        }

      }

      if ( ! ( container is Control ) || ! inheritable )
      {
        if ( debugInfo != null )
        {
          debugInfo.LogInfo( "Container is null/! inheritable", container, inheritable );
        }
        return null;
      }

      var control = container as Control;
      UIColorTransition parentTransition = null;

      if ( debugInfo != null )
      {
        debugInfo.LogInfo( "Checking parents:", HierarchyName.Of( control  ) );
      }

      NodesWalker.Get().GetInParents( control, 
        it => 
        {
          if ( debugInfo != null )
          {
            debugInfo.LogInfo( "Processing Parent:", HierarchyName.Of( it ) );
          }

          if ( ! ( it is UIStylePropertyContainer ) )
          {
            if ( debugInfo != null )
            {
              debugInfo.LogInfo( "Not a style container:" );
            }
            
            return false;
          }

          var container = (UIStylePropertyContainer) it;
          parentTransition = _GetTransition( true, container, property, shaderPropertyName );

          if ( debugInfo != null )
          {
            debugInfo.LogInfo( "Transition of parent:", parentTransition );
          }

          return parentTransition != null;
        }
      );

      if ( debugInfo != null )
      {
        debugInfo.LogInfo( "Processing Parents done, result:", parentTransition );
      }

      return parentTransition; 

    }

    public static float GetCurrentFontSize( Control n )
    {
      if ( n == null )
      {
        return 12;
      }

      var ui = UIHolder.GetUI( n );

      if ( ui == null )
      {
        return 12;
      }
      
      var container = n as UIStylePropertyContainer;

      if ( container == null )
      {
        container = UIStylePropertyContainer.FindInParents( n );
      }

      if ( container == null )
      {
        return ui.X_computedFontSizePixels;
      }

      // RJLog.Log( "Computing font size from:", HierarchyName.Of( container as Node ) );
      // debugInheritable = true;
      var size = UINumber.Compute( container as Control, UIStyleNumberProperty.FontSize, 0, 100 );

      // RJLog.Log( "Computed font size:", size );
      // debugInheritable = false;
      return size;
    }

    // static bool debugInheritable = false;

    public static UINumber GetInheritableNumberProperty( UIStylePropertyContainer container, 
    UIStyleNumberProperty property, string shaderPropertyName, UIStylePropertyContainer source  )
    {
      if ( container == null )
      {
        return null;
      }

      var ownProperty = container.GetUIStyleNumberProperty( property, shaderPropertyName, source );

      if ( ownProperty != null )
      {
        return ownProperty;
      }

      var parentStyle = container.GetUIStyleParent();
      var parentStyleProperty = GetReferenceableNumberProperty( parentStyle, property, shaderPropertyName, source );

      if ( parentStyleProperty != null )
      {
        return parentStyleProperty;
      }

      if ( ! ( container is Control ) )
      {
        return null;
      }

      var control = container as Control;
      UINumber parentNumber = null;

      // if ( debugInheritable )
      // {
      //   RJLog.Log( "Searching inheritable:", property, HierarchyName.Of( container as Node ) );
      // }


      NodesWalker.Get().GetInParents( control, 
        it => 
        {
          // if ( debugInheritable && UIStyleNumberProperty.FontSize == property )
          // {
          //   RJLog.Log( "Searching inheritable:", property, HierarchyName.Of( it ) );
          // }
          
          if ( it is UI ui )
          {
            var uiNumber = ui.GetUINumber( property );

            if ( uiNumber != null )
            {
              parentNumber = uiNumber;
              // RJLog.Log( "Found ui number in UI:", uiNumber );
              
              return true;
            }
          }

          if ( ! ( it is UIStylePropertyContainer ) )
          {
            return false;
          }

          var container = (UIStylePropertyContainer) it;
          parentNumber = GetReferenceableNumberProperty( container, property, shaderPropertyName, source );

          return parentNumber != null;
        }
      );
      
      return parentNumber;      
            
    } 

    public static UIColor GetInheritableColorProperty( UIStylePropertyContainer container, 
      UIStyleColorProperty property, string shaderPropertyName, UIStylePropertyContainer source  )
    {
      if ( container == null )
      {
        return null;
      }

      var ownProperty = container.GetUIStyleColorProperty( property, shaderPropertyName, source  );

      if ( ownProperty != null )
      {
        return ownProperty;
      }

      var parentStyle = container.GetUIStyleParent();
      var parentStyleProperty = GetReferenceableColorProperty( parentStyle, property, shaderPropertyName, source  );

      if ( parentStyleProperty != null )
      {
        return parentStyleProperty;
      }

      if ( ! ( container is Control ) )
      {
        return null;
      }

      var control = container as Control;
      UIColor parentColor = null;

      NodesWalker.Get().GetInParents( control, 
        it => 
        {
          if ( ! ( it is UIStylePropertyContainer ) )
          {
            return false;
          }

          var container = (UIStylePropertyContainer) it;
          parentColor = GetReferenceableColorProperty( container, property, shaderPropertyName, source );

          return parentColor != null;
        }
      );

      return parentColor;      
            
    } 

    public static UIPosition Position( UIStylePropertyContainer container )
    {
      if ( container == null )
      {
        return UIPosition.___;
      }

      var ownProperty = container.GetUIPosition();

      if ( ownProperty != UIPosition.___ )
      {
        return ownProperty;
      }

      var parent = container.GetUIStyleParent();

      if ( parent == null )
      {
        return UIPosition.___;
      }

      return parent.GetUIPosition();
    }

    public static UILayout Layout( UIStylePropertyContainer container )
    {
      if ( container == null )
      {
        return UILayout.___;
      }

      var ownProperty = container.GetUILayout();

      if ( ownProperty != UILayout.___ )
      {
        return ownProperty;
      }

      var parent = container.GetUIStyleParent();

      if ( parent == null )
      {
        return UILayout.___;
      }

      return parent.GetUILayout();
    }

    public static UILineWrap LineWrap( UIStylePropertyContainer container )
    {
      if ( container == null )
      {
        return UILineWrap.___;
      }

      var ownProperty = container.GetUILineWrap();

      if ( ownProperty != UILineWrap.___ )
      {
        return ownProperty;
      }

      var parent = container.GetUIStyleParent();

      if ( parent == null )
      {
        return UILineWrap.___;
      }

      return parent.GetUILineWrap();
    }


    static Font GetFontFromOwnOrStyleParent( UIStylePropertyContainer container ) 
    {
      if ( container == null )
      {
        return null;
      }

      var ownFont = container.GetFont();

      if ( ownFont != null )
      {
        return ownFont;
      }

      var parent = container.GetUIStyleParent();

      if ( parent == null )
      {
        return null;
      }

      return parent.GetFont();

    }

    public static Font Font( UIStylePropertyContainer container )
    {
      var font = GetFontFromOwnOrStyleParent( container );

      if ( font != null )
      {
        return font;
      }

      if ( ! ( container is Control ) )
      {
        return null;
      }

      var control = container as Control;
      font = null;

      NodesWalker.Get().GetInParents( control, 
        it => 
        {
          if ( ! ( it is UIStylePropertyContainer ) )
          {
            return false;
          }

          var container = (UIStylePropertyContainer) it;
          font = GetFontFromOwnOrStyleParent( container );

          return font != null;
        }
      );

      if ( font == null )
      {
        var ui = UI.Get( control );

        if ( ui != null && ui.settings != null )
        {
          return ui.settings.defaultFont;
        }

      }

      return font;      
    }

    public static UINumber GetUINumberProperty( UIStylePropertyContainer container, 
    UIStyleNumberProperty property, string shaderPropertyName, UIStylePropertyContainer source )
    {
      switch ( property )
      {
        case UIStyleNumberProperty.FontSize:
        case UIStyleNumberProperty.FontOutlineSize:
        case UIStyleNumberProperty.FontShadowSize:
        case UIStyleNumberProperty.FontShadowOffsetX:
        case UIStyleNumberProperty.FontShadowOffsetY:
        case UIStyleNumberProperty.FloatShaderProperty:
        {
          return GetInheritableNumberProperty( container, property, shaderPropertyName, source );
        }
      }

      return GetReferenceableNumberProperty( container, property, shaderPropertyName, source );
    }

    public static UIColor GetUIColorProperty( UIStylePropertyContainer container, 
              UIStyleColorProperty property, string shaderPropertyName, UIStylePropertyContainer source )
    {
       switch ( property )
      {
        case UIStyleColorProperty.FontColor:
        case UIStyleColorProperty.FontOutlineColor:
        case UIStyleColorProperty.FontShadowColor:
        case UIStyleColorProperty.ColorShaderProperty:
        {
          return GetInheritableColorProperty( container, property, shaderPropertyName, source );
        }
      }

      return GetReferenceableColorProperty( container, property, shaderPropertyName, source );
    }

  }

}