
using Godot;
using System.Collections.Generic;

namespace Rokojori
{  
  public class CEG_TextureCreator
  {
    public bool autoClean = true;

    public void AutoClean( RDTexture texture, RenderingDevice rd )
    {
      if ( texture == null || ! autoClean )
      {
        return;
      }

      rd.FreeRid( texture.rid );
      
    }

    public virtual RDTexture Create( RDTexture texture, _XX_CompositorEffectGraph graph )
    {
      return texture;
    }
  }

  public class CEG_TextureCreator_ScreenSize:CEG_TextureCreator
  {
    public RDTextureFormat format = RDTexture.DefaultFormat( -1, -1 );
    public Vector2 scale = Vector2.One;

    public override RDTexture Create( RDTexture texture, _XX_CompositorEffectGraph graph )
    {
      Vector2I scaledSize = (Vector2I) ( graph.context.internalSize * scale );

      if ( texture == null || scaledSize != texture.size )
      {
        AutoClean( texture, graph.rd );
        format = RDTexture.FormatChangeSize( format, scaledSize );
        texture = RDTexture.Create( graph, format );
      }

      return texture;
    }
  }

  public class CEG_TextureCreator_FixedSize:CEG_TextureCreator
  {
    public RDTextureFormat format = RDTexture.DefaultFormat( -1, -1 );

    public override RDTexture Create( RDTexture texture, _XX_CompositorEffectGraph graph )
    {
      var formatSize = new Vector2I( (int) format.Width, (int) format.Height );

      if ( texture == null || texture.size != formatSize )
      {
        AutoClean( texture, graph.rd );
        texture = RDTexture.Create( graph, format );
      }

      return texture;
    }
  }



  public class CEG_BufferTexture:CompositorEffectGraphProcessor, CompositorEffectGraphTextureSlotInput
  {
    RDTexture _texture;

    CEG_TextureCreator _creator;


    public RDTexture GetTexture()
    {
      return _texture;
    }

    public CompositorEffectGraphProcessor GetProcessor()
    {
      return this;
    } 

    List<CompositorEffectGraphTextureSlot> _connectedSlots = new List<CompositorEffectGraphTextureSlot>();

    public void SetConnected( CompositorEffectGraphTextureSlot slot )
    {
      _connectedSlots.Add( slot );
    }

    public CEG_BufferTexture( _XX_CompositorEffectGraph graph, CEG_TextureCreator creator ):base( graph )
    {
      _creator = creator;
    } 

    public static CEG_BufferTexture ScreenSize( _XX_CompositorEffectGraph graph, Vector2? scale = null )
    {
      var screenSize = new CEG_TextureCreator_ScreenSize();
      screenSize.scale = scale == null ? Vector2.One : (Vector2) scale;
      return new CEG_BufferTexture( graph, screenSize );
    }

    public static CEG_BufferTexture FixedSize( _XX_CompositorEffectGraph graph )
    {
      return new CEG_BufferTexture( graph, new CEG_TextureCreator_FixedSize() );
    }

    public override void Process()
    {
      _texture = _creator.Create( _texture, graph );
    }

    public void ConnectTo( CompositorEffectGraphTextureSlot slot )
    {
      slot.SetInput( this );
    }
    
  }
}