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

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

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

    [Export( PropertyHint.Range, "0,1")]
    public float edgeTreshold = 0.2f;

    [Export( PropertyHint.Range, "1,4")]
    public float edgeTresholdPower = 1f;
    
    [Export( PropertyHint.Range, "0,4")]
    public float edgeIntensity = 2f;

    [Export( PropertyHint.Range, "0,1")]
    public float blurMix = 0.25f;

    public enum BlurMode
    {
      UniDirectional,
      BiDirectional
    }

    [Export]
    public BlurMode blurMode = BlurMode.UniDirectional;

    [Export( PropertyHint.Range, "1,10" )]
    public int blurSpread = 1;

    RG_ScreenColorTexure screenColorTexture;

    RG_DAA _daa0;
    RG_DAA _daa1;
    RG_DAA _daa2;
    RG_DAA _daa3;

    List<RG_DAA> _daa = [];

  
    void Initialize()
    { 
      EffectCallbackType = EffectCallbackTypeEnum.PostOpaque;

      screenColorTexture = new RG_ScreenColorTexure( graph );
      _daa0 = new RG_DAA( graph );
      _daa1 = new RG_DAA( graph );
      _daa2 = new RG_DAA( graph );
      _daa3 = new RG_DAA( graph );

      graph.InitializeNodes();      

      _daa = [ _daa0, _daa1, _daa2, _daa3 ];

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


      graph.SetProcessOrder( 
        screenColorTexture, 
        _daa0, 
        _daa1,
        _daa2,
        _daa3 
      );
    }

    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 ( lastIterations != numIterations )
      {
        lastIterations = numIterations;
        var list = new List<RGGraphProcessor>();

        list.Add( screenColorTexture );

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

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

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

        _daa[ i ].constants.Set(        
          fxAmount,
          Mathf.Pow( edgeTreshold, edgeTresholdPower ),
          edgeIntensity,
          blurMix,

          (float)blurMode,
          (float)blurSpread,
          0f,
          0f
        );
      }

      
    }
  }
}