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

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

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

    [Export( PropertyHint.Range, "0,100")]
    public float noise = 2f;

    [Export( PropertyHint.Range, "1,100")]
    public int kernelOffset = 2;

    [Export( PropertyHint.Range, "1,30")]
    public int kernelRadius = 2;    

    [Export( PropertyHint.Range, "1,4")]
    public int iterations = 2;


    RG_ScreenColorTexure screenColorTexture;
    RG_BufferTexture bufferTexture;    

    CEG_Copy copy;
    CEG_Copy copy2;
    RG_BoxBlur boxBlur;    
    RG_BoxBlur boxBlur1; 
    RG_BoxBlur boxBlur2; 
    RG_BoxBlur boxBlur3; 

    List<RG_BoxBlur> _blurs;

    void Initialize()
    { 
      screenColorTexture = new RG_ScreenColorTexure( graph );
      bufferTexture = RG_BufferTexture.ScreenSize( graph );

      copy = new CEG_Copy( graph );
      copy2 = new CEG_Copy( graph );
      boxBlur = new RG_BoxBlur( graph );
      boxBlur1 = new RG_BoxBlur( graph );
      boxBlur2 = new RG_BoxBlur( graph );
      boxBlur3 = new RG_BoxBlur( graph );

      _blurs = new List<RG_BoxBlur>()
      {
        boxBlur, boxBlur1, boxBlur2, boxBlur3
      };

      graph.InitializeNodes();

      copy.SetTextureSlotInputs( screenColorTexture, bufferTexture );
      boxBlur.SetTextureSlotInputs( copy.output, copy.input );
      boxBlur1.SetTextureSlotInputs( boxBlur.output, boxBlur.input );
      boxBlur2.SetTextureSlotInputs( boxBlur1.output, boxBlur1.input ); 
      boxBlur3.SetTextureSlotInputs( boxBlur2.output, boxBlur2.input ); 
      
    }

    int _lastIterations = -1;

    
    protected override void ForAllViews()
    {
      

      SetOrderForIterations();

      _blurs.ForEach(
        blur =>
        {
           blur.constants.Set(        
            intensity,
            noise,
            (float)kernelOffset,
            (float)kernelRadius          
          );
        }
      );     
     
    }

    void SetOrderForIterations()
    {
      iterations = Mathf.Clamp( iterations, 1, _blurs.Count );

      if ( _lastIterations == iterations )
      {
        return;
      }

      var list = new List<RGGraphProcessor>
      {
        screenColorTexture,
        bufferTexture,
        copy
      };

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

      if ( iterations % 2 == 0 )
      {
        var lastBlur = _blurs[ iterations - 1 ];
        copy2.SetTextureSlotInputs( lastBlur.output, lastBlur.input );
        list.Add( copy2 );
      }

      _lastIterations = iterations;

      

      graph.SetProcessOrder( list );

    }
    

   
  }
}