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

namespace Rokojori
{ 
  [Tool]
  public class ActiveStyleTransition<V,P> 
  {
    public V value;
    public List<V> lastValues = [];
    public List<float> lastWeights = [];
    public P propertyType;
    public TimeLine timeLine;
    public float start;
    public float end; 
    public Curve curve;
    public bool transitioning;
   

    public float GetUnclampedTransitionPhase()
    {
      var transitionPhase = timeLine.ComputeRange( start, end );
      return transitionPhase;
    }

    public float ComputeTransitionWeight( float phase )
    {
      var amount = MathX.Clamp01( phase );

      if ( curve != null )
      {
        amount = curve.Sample( amount );
      }

      return amount;
    }

    public float GetTransitionWeight()
    {
      var transitionPhase = GetUnclampedTransitionPhase();
      return ComputeTransitionWeight( transitionPhase );
    }

    public void EndTransition()
    {
      transitioning = false;
      lastValues = [];
      lastWeights = [];

    }

    public void StartTransition( Control control, V nextValue, TransitionSettings transitionSettings )
    {
      if ( ! transitioning )
      {
        lastValues = [ value ];
        lastWeights = [ 1f ];
      }
      else
      {
        var valueWeight = GetTransitionWeight();
        var lastWeight = 1f - valueWeight;

        for ( int i = 0; i < lastWeights.Count; i++ )
        {
          lastWeights[ i ] *= lastWeight;
        }

        lastValues.Add( value );
        lastWeights.Add( valueWeight );
      }

      value = nextValue;

      timeLine = UI.GetTimeLine( control, transitionSettings.timeLine );       
      start = timeLine.position;
      end = start + transitionSettings.duration;
      transitioning = true;          
      curve = transitionSettings.curve;
    }

    // public static O ProcessTransition<O>( 
    //   UIStylePropertyContainer container, O computedValue, 
    //   List<ActiveStyleTransition<V,P>> activeTransitions, V activeValue, P property,
    //   Func<TransitionSettingsAll> getTransitionSettings,
    //   Func<V,O> computeValue,
    //   Func<O,O,float,O> lerpValue 
    //   )
    // {
    //   var propertyTransition = activeTransitions.Find( t => t != null && EqualityComparer<P>.Default.Equals( t.propertyType, property ) );

    //   if ( propertyTransition == null )
    //   {
    //     propertyTransition = new ActiveStyleTransition<V, P>();
    //     propertyTransition.propertyType = property;
    //     propertyTransition.value = activeValue;         
    //     propertyTransition.transitioning = false;

    //     activeTransitions.Add( propertyTransition );

    //     return computedValue;
    //   } 
    //   else
    //   {
    //     if ( ! EqualityComparer<V>.Default.Equals( propertyTransition.value, activeValue ) && 
    //     ! propertyTransition.transitioning && getTransitionSettings() != null )
    //     {
    //       var transitionSettings = getTransitionSettings();
    //       propertyTransition.timeLine = transitionSettings.timeLine;       
    //       propertyTransition.start = transitionSettings.timeLine.position;
    //       propertyTransition.end = propertyTransition.start + transitionSettings.duration;
    //       propertyTransition.transitioning = true;          
    //       propertyTransition.curve = transitionSettings.curve;
    //     }
    //   }

    //   if ( EqualityComparer<V>.Default.Equals( propertyTransition.value, activeValue ) )
    //   {
    //     propertyTransition.transitioning = false;
    //     return computedValue;
    //   }

    //   var computedTransitionValue = computeValue( propertyTransition.value );

    //   var transitionPhase = propertyTransition.timeLine.ComputeRange( propertyTransition.start, propertyTransition.end );
     
    //   if ( transitionPhase >= 1 )
    //   {
    //     activeTransitions.Remove( propertyTransition );
    //   }

    //   var amount = MathX.Clamp01( transitionPhase );
    //   var curveAmount = amount;

    //   if ( propertyTransition.curve != null )
    //   {
    //     curveAmount = propertyTransition.curve.Sample( curveAmount );
    //   }

    //   return lerpValue( computedTransitionValue, computedValue, curveAmount );
    // }
  }
}