
using Godot;
using Rokojori;
 
namespace Rokojori
{ 
  public enum UIColorAnimationBlend
  {
    Multiply,
    Add,
    Replace
  }

  [Tool]
  [GlobalClass] 
  public partial class UIColor : Resource
  { 
    [Export]
    public Color color = Colors.White;

    [Export]
    public bool isAnimated = false;

    [Export]
    public Gradient animationGradient;

    [Export]
    public ColorBlendModeType blendMode = ColorBlendModeType.Multiply;

    [Export]
    public float animationDuration = 1;

    [Export]
    public float animationOffset = 0;

    [Export]
    public TimeLine timeLine;


    public static Color Compute( Control control, UIStyleColorProperty property, string shaderPropertyName, Color defaultColor )
    {
      var container = control as UIStylePropertyContainerNode;

      // Get selected ui color
      var uiColor = UIStyle.GetUIColorProperty( container, property, shaderPropertyName, container );

      if ( uiColor != null && uiColor.isAnimated )
      {
        container.SetAnimatedFlag();
      }

      var computedColor = Compute( control, uiColor, defaultColor );      

      // if ( property != UIStyleColorProperty.ColorShaderProperty )
      // {
      //   UIStyle.debugInfo = control;

      //   control.LogInfo( "=========== CHECKING COLOR =================" );
      // }
      var transition = UIStyle.GetTransition( container, property, shaderPropertyName );

      // if ( property != UIStyleColorProperty.ColorShaderProperty )
      // {
      //   UIStyle.debugInfo = null;
      // }

      var transitionAll = UIStyle.GetTransitionSettingsAll( container );

      var usesTransition = transition != null || transitionAll != null && transitionAll.transitionAllProperties;

      // if ( property != UIStyleColorProperty.ColorShaderProperty )
      // {
      //   RJLog.Log( HierarchyName.Of( control ), "Uses Transition:", property, usesTransition, transition, transitionAll );
      // }

      if ( ! usesTransition )
      {
        return computedColor; 
      }     

      var activeColorTransitions = container.GetActiveUIColorTransitions();

      var propertyTransition = activeColorTransitions.Find( t => t != null && t.propertyType.Matches( property, shaderPropertyName ) );
      propertyTransition = EnsureTransitionObject( propertyTransition, control, uiColor, property, shaderPropertyName );      

      var endValueChanged = uiColor != propertyTransition.value;

      if ( endValueChanged )
      {
        var transitionSettings = UIStyle.GetTransitionSettings( container, property, shaderPropertyName );
        
        if ( transitionSettings == null )
        {
          control.LogInfo( ">> No transition settings", property );
        }

        propertyTransition.StartTransition( control, uiColor, transitionSettings );
      }

      if ( ! propertyTransition.transitioning )
      {
        return computedColor;
      }

      var computedTransitionValue = new Color( 0, 0, 0, 0 );
      
      for ( int i = 0; i < propertyTransition.lastValues.Count; i++ )
      {
        var lastValue = Compute( control, propertyTransition.lastValues[ i ], defaultColor ); 
        computedTransitionValue += lastValue * propertyTransition.lastWeights[ i ];
      }

      var phase = propertyTransition.GetUnclampedTransitionPhase();
      var lerpWeight = propertyTransition.ComputeTransitionWeight( phase );

      if ( phase >= 1f )
      {
        propertyTransition.EndTransition();
      }

      var result = ColorX.Lerp( computedTransitionValue, computedColor, lerpWeight );

      return result;
    }

    static ActiveStyleTransition<UIColor, UIStyleColorPropertyAndName> EnsureTransitionObject( 
      ActiveStyleTransition<UIColor, UIStyleColorPropertyAndName> propertyTransition, 
      Control control, UIColor uiColor, UIStyleColorProperty property, string shaderPropertyName )
    {

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

      var container = control as UIStylePropertyContainer;
      propertyTransition = new ActiveStyleTransition<UIColor, UIStyleColorPropertyAndName>();
      propertyTransition.propertyType = UIStyleColorPropertyAndName.Create( property, shaderPropertyName );
              
      var transitionSettings = UIStyle.GetTransitionSettings( container, property, shaderPropertyName );
      propertyTransition.value = uiColor; 
      propertyTransition.timeLine = UI.GetTimeLine( control, transitionSettings.timeLine );        
      propertyTransition.transitioning = false;

      container.GetActiveUIColorTransitions().Add( propertyTransition );

      return propertyTransition;
    }

    public static Color Compute( Control control, UIColor color, Color defaultColor )
    {
      if ( color == null )
      {
        return defaultColor;
      }

      if ( ! color.isAnimated || color.animationGradient == null )
      {
        return color.color;
      }

      var timeLine = UI.GetTimeLine( control, color.timeLine );
      
      var phase = timeLine.ComputePhase( color.animationDuration, color.animationOffset );

      var gradientColor = color.animationGradient.Sample( phase );

      return ColorBlendMode.Blend( color.blendMode, color.color, gradientColor );

    }

  }
}