
using Godot;
using System.Collections.Generic;

namespace Rokojori
{  
  public interface RDGraphTextureSlotInput
  {
    public RDTexture GetTexture();
    public RGGraphProcessor GetProcessor();
    public void SetConnected( CompositorEffectGraphTextureSlot slot );
    public void ConnectTo( CompositorEffectGraphTextureSlot slot );

    public void SetDisconnected( CompositorEffectGraphTextureSlot slot );
    public void Disconnect( CompositorEffectGraphTextureSlot slot );
  }

  public class CompositorEffectGraphTextureSlot:RDGraphConnection, RDGraphTextureSlotInput
  {
    protected RDGraphTextureSlotInput _input;
    public RDGraphTextureSlotInput input => _input;

    public RDSampler sampler;

    protected RDTexture _texture;
    
    public void UseSampler( RenderingDevice.SamplerFilter filter = RenderingDevice.SamplerFilter.Linear, RenderingDevice.SamplerRepeatMode repeatMode = RenderingDevice.SamplerRepeatMode.Repeat )
    {
      sampler = graph.context.Sampler( filter, repeatMode );
    }

    public void UseLinearSampler( RenderingDevice.SamplerRepeatMode repeatMode = RenderingDevice.SamplerRepeatMode.Repeat )
    {
      sampler = graph.context.Sampler( RenderingDevice.SamplerFilter.Linear, repeatMode );
    }

    public void UseLinearSamplerEdgeClamped()
    {
      UseLinearSampler( RenderingDevice.SamplerRepeatMode.ClampToEdge );
    }

    public void UseLinearSamplerMirroredRepeat()
    {
      UseLinearSampler( RenderingDevice.SamplerRepeatMode.MirroredRepeat );
    }

    public void UseNearestSampler( RenderingDevice.SamplerRepeatMode repeatMode = RenderingDevice.SamplerRepeatMode.Repeat )
    {
      sampler = graph.context.Sampler( RenderingDevice.SamplerFilter.Nearest, repeatMode );
    }

    public void UseNearestSamplerEdgeClamped()
    {
      UseNearestSampler( RenderingDevice.SamplerRepeatMode.ClampToEdge );
    }

    public void UseNearestSamplerMirroredRepeat()
    {
      UseNearestSampler( RenderingDevice.SamplerRepeatMode.MirroredRepeat );
    }

    public void UseSamplerNoRepeat( RenderingDevice.SamplerFilter filter = RenderingDevice.SamplerFilter.Linear )
    {
      sampler = graph.context.Sampler( filter, RenderingDevice.SamplerRepeatMode.ClampToEdge );
    }

    public RDTexture GetTexture()
    {
      return _texture;
    }

    public RDTexture ResolveTexture()
    {
      return _texture = _input.GetTexture();
    }

    public RGGraphProcessor GetProcessor()
    {
      return _processor;
    }

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

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

    public void SetDisconnected( CompositorEffectGraphTextureSlot slot )
    {
      _connectedSlots.Remove( slot );
    }

    public CompositorEffectGraphTextureSlot( RGGraphProcessor processor ):base( processor )
    {

    }

    public void SetInput( RDGraphTextureSlotInput input )
    {
      if ( input == _input )
      {
        return;
      }
      
      _input = input;
      input.SetConnected( this );
    }

    public void ReplaceInput( RDGraphTextureSlotInput oldInput, RDGraphTextureSlotInput newInput )
    {
      RemoveInput( oldInput );
      SetInput( newInput );
    }

    public void RemoveInput( RDGraphTextureSlotInput input )
    {
      if ( input != _input )
      {
        return;
      }

      _input.SetDisconnected( this );
      _input = null;
    }

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

    public void Disconnect( CompositorEffectGraphTextureSlot slot )
    {
      slot.RemoveInput( this );
    }
  }

  public class RG_TextureSlotEditable:CompositorEffectGraphTextureSlot
  {
    public RG_TextureSlotEditable( RGGraphProcessor processor ):base( processor ){}

    public void SetTexture( RDTexture texture )
    {
      _texture = texture;
    }
  }
}