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

namespace Rokojori
{ 

  [Tool]
  [GlobalClass] 
  public partial class UIStyle:Resource, UIStylePropertyContainer
  {
    [Export]
    public UIStyle parentStyle;

    [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( "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,UIStyleNumberProperty>> GetActiveUINumberTransitions()
    {
      return null;
    }

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


    public UIStyle GetUIStyleParent()
    {
      return parentStyle;
    }

    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 )
    {
      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;
      }

      return null;
    }

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

    public UIColor GetUIStyleColorProperty( UIStyleColorProperty property )
    {
      switch ( property )
      {
        case UIStyleColorProperty.FontColor:         return fontColor;
        case UIStyleColorProperty.FontOutlineColor:  return outlineColor;
        case UIStyleColorProperty.FontShadowColor:   return shadowColor;
      } 

      return null;
    }

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

      var ownProperty = container.GetUIStyleNumberProperty( property );

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

      var style = container.GetUIStyleParent();

      return GetReferenceableNumberProperty( style, property );
    } 

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

      var ownProperty = container.GetUIStyleColorProperty( property );

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

      var style = container.GetUIStyleParent();

      return GetReferenceableColorProperty( style, property );
    } 

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

      return _GetTransition( false, container, property );
    
    }

    static UINumberTransition _GetTransition( bool inheritable, UIStylePropertyContainer container, UIStyleNumberProperty property )
    {
      var transitions = container.GetNumberTransitions();

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

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

      var styleParent = container.GetUIStyleParent();

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

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

      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 );

          return parentTransition != null;
        }
      );

      return parentTransition; 

    }

    public static TransitionSettingsAll GetTransitionSettingsAll( UIStylePropertyContainer container )
    {
      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 )
    {
      var transition = GetTransition( container, colorProperty );

      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 );
    }
    
    public static TransitionSettings GetTransitionSettings( UIStylePropertyContainer container, UIStyleNumberProperty numberProperty )
    {
      var transition = GetTransition( container, numberProperty );

      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 );
    }

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

      return _GetTransition( false, container, property );
    
    }

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

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

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

      var styleParent = container.GetUIStyleParent();

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

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

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

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

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

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

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

          return parentTransition != null;
        }
      );

      return parentTransition; 

    }


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

      var ownProperty = container.GetUIStyleNumberProperty( property );

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

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

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

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

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

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

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

          return parentNumber != null;
        }
      );

      return parentNumber;      
            
    } 

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

      var ownProperty = container.GetUIStyleColorProperty( property );

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

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

      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 );

          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 = control.FindParentThatIs<UI>();

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

      }

      return font;      
    }

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

      return GetReferenceableNumberProperty( container, property );
    }

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

      return GetReferenceableColorProperty( container, property );
    }

  }

}