
using Godot;

namespace Rokojori
{  
  public class RDTexture: RenderingObject
  {
    public RDTexture( RokojoriCompositorEffect effect, Rid rid ):base( effect, rid ){}

    public static RDTexture Create( RokojoriCompositorEffect effect, RDTextureFormat format, RDTextureView view )
    {
      return new RDTexture( effect, effect.rd.TextureCreate( format, view ) );  
    }

    public static RDTexture Color( RokojoriCompositorContext context )
    {
      var rid = context.sceneBuffers.GetColorLayer( (uint) context.view );

      return new RDTexture( context.effect, rid );  
    }

    public static RDTexture Depth( RokojoriCompositorContext context )
    {
      var rid = context.sceneBuffers.GetDepthLayer( (uint) context.view );

      return new RDTexture( context.effect, rid );  
    }

    public RDTextureFormat format 
    {
      get
      {
        return effect.rd.TextureGetFormat( rid );
      }
    }

    public Vector2I size 
    {
      get 
      {
        var textureFormat = format;
        return new Vector2I( (int) textureFormat.Width, (int) textureFormat.Height ); 
      }
    }

    public static RDTexture Create( RokojoriCompositorEffect effect, RDTextureFormat format )
    {
      var view = new RDTextureView();
      var rid = effect.rd.TextureCreate( format, view ); 
      return new RDTexture( effect, rid );  
    }

    public static RDTextureFormat DefaultFormat( int w, int h,  RenderingDevice.DataFormat dataFormat = RenderingDevice.DataFormat.R16G16B16A16Unorm )
    {
      var format = new RDTextureFormat();

      format.Width  = (uint) w;
      format.Height = (uint) h;
      format.Format = dataFormat;
      format.UsageBits = RenderingDevice.TextureUsageBits.StorageBit | RenderingDevice.TextureUsageBits.SamplingBit;

      return format;
    }

    public static RDTextureFormat FormatChangeSize( RDTextureFormat tf, Vector2I size )
    {
      return FormatChangeSize( tf, size.X, size.Y );
    }
    
    public static RDTextureFormat FormatChangeSize( RDTextureFormat tf, int w, int h )
    {
      var clone = FormatCopy( tf );
      clone.Width = (uint) w;
      clone.Height = (uint) h;
      return clone;
    }

    public static RDTextureFormat FormatCopy( RDTextureFormat tf )
    {
      var format = new RDTextureFormat();

      format.Format = tf.Format;

      format.Width  = tf.Width;
      format.Height = tf.Height;
      format.Depth = tf.Depth;

      format.ArrayLayers = tf.ArrayLayers;
      format.Mipmaps = tf.Mipmaps;
      format.TextureType = tf.TextureType;
      format.Samples = tf.Samples;      
      format.UsageBits = tf.UsageBits;
      format.IsResolveBuffer = tf.IsResolveBuffer;
      format.IsDiscardable = tf.IsDiscardable;

      return tf;

    }

    public static RDTexture Create( RokojoriCompositorEffect effect, Vector2I size, RenderingDevice.DataFormat dataFormat = RenderingDevice.DataFormat.R16G16B16A16Unorm )
    {
      return Create( effect, size.X, size.Y, dataFormat );
    }

    public static RDTexture Create( RokojoriCompositorEffect effect, int width, int height, 
                                    RenderingDevice.DataFormat dataFormat = RenderingDevice.DataFormat.R16G16B16A16Unorm )
    {
      var view   = new RDTextureView();
      var format = DefaultFormat( width, height, dataFormat );

      var rid = effect.rd.TextureCreate( format, view ); 
      return new RDTexture( effect, rid );  
    }
  }
}