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

namespace Rokojori
{  
  [Tool]
  [GlobalClass]
  public partial class FXAAEffect:AntiAliasingEffect
  {
    public FXAAEffect():base()
    {
      Initialize();
    }

    
    [Export( PropertyHint.Range, "0,4")]
    public float amount = 1;

    public enum ExecutionMode
    {
      Ints_FullAmount_Fraction_PartialAmount,
      Four_With_PartialAmount
    }

    [Export]
    public ExecutionMode executionMode = ExecutionMode.Ints_FullAmount_Fraction_PartialAmount;

    // [Export( PropertyHint.Range, "0,2")]
    // public float exposure = 1f;
    
    // [Export( PropertyHint.Range, "0,2")]
    // public float luminance_multiplier = 1f;
    

    RG_ScreenColorTexure screenColorTexture;

    RG_FXAA _fxaa0;
    RG_FXAA _fxaa1;
    RG_FXAA _fxaa2;
    RG_FXAA _fxaa3;

    List<RG_FXAA> _fxaa = [];

  
    void Initialize()
    { 
      screenColorTexture = new RG_ScreenColorTexure( graph );
      _fxaa0 = new RG_FXAA( graph );
      _fxaa1 = new RG_FXAA( graph );
      _fxaa2 = new RG_FXAA( graph );
      _fxaa3 = new RG_FXAA( graph );

      graph.InitializeNodes();      

      _fxaa = [ _fxaa0, _fxaa1, _fxaa2, _fxaa3 ];

      _fxaa.ForEach( fx => 
      {
        fx.input.sampler = context.Sampler( RenderingDevice.SamplerFilter.Linear, RenderingDevice.SamplerRepeatMode.ClampToEdge );
        fx.SetTextureSlotInputs( screenColorTexture, screenColorTexture );
      }
      );


      graph.SetProcessOrder( 
        screenColorTexture, 
        _fxaa0, 
        _fxaa1,
        _fxaa2,
        _fxaa3 
      );
    }

    int lastIterations = -1;

    protected override void ForAllViews()
    {
      var clampedAmount = Mathf.Min( 3.99999999f, amount );
      int numIterations = Mathf.CeilToInt( clampedAmount ); 
      var partialAmount = amount - ( numIterations - 1  );

      if ( ExecutionMode.Four_With_PartialAmount == executionMode )
      {
        numIterations = 4;
      }
  

      if ( lastIterations != numIterations )
      {
        lastIterations = numIterations;
        var list = new List<RGGraphProcessor>();

        list.Add( screenColorTexture );

        for ( int i = 0; i < numIterations; i++ )
        {
          list.Add( _fxaa[ i ] );
        }

        graph.SetProcessOrder( list.ToArray() );
      }

      for ( int i = 0; i < numIterations; i++ )
      {
        float fxAmount = i == ( numIterations - 1 ) ? partialAmount : 1f;

        if ( ExecutionMode.Four_With_PartialAmount == executionMode )
        {
          fxAmount = amount / 4.0f;
        }

        _fxaa[ i ].constants.Set(        
          1f,
          1f,
          fxAmount
        );
      }

      
    }
  }
}