using Godot;
namespace Rokojori
{  
  public static class ImageExtensions
  {

     public enum EdgeMode
    {
      Clamp,
      Repeat,
      TransparentBlack,
    }


    public static Color GetPixel( this Image image, int x, int y, EdgeMode mode )
    {
      if ( x < 0 || y < 0 || x >= image.GetSize().X || y >= image.GetSize().Y )
      {
        if ( mode == EdgeMode.TransparentBlack )
        {
          return new Color( 0, 0, 0, 0 );
        }

        if ( mode == EdgeMode.Repeat )
        {
          x = MathX.Repeat( x, image.GetSize().X );
          y = MathX.Repeat( y, image.GetSize().Y ); 
        }

        if ( mode == EdgeMode.Clamp )
        {
          x = Mathf.Clamp( x, 0, image.GetSize().X );
          y = Mathf.Clamp( y, 0, image.GetSize().Y ); 
        }
      }

      return image.GetPixel( x, y );
    }

    
    public static Color SampleNearest( this Image image, Vector2 uv, EdgeMode mode = EdgeMode.Clamp )
    {
      var pixelUV = uv * image.GetSize(); 
      var roundedPixelUV = pixelUV.RoundToInt();
      return image.GetPixel( roundedPixelUV.X, roundedPixelUV.Y, mode );
    }

    public static Color SampleLinear( this Image image, Vector2 uv, EdgeMode mode = EdgeMode.Clamp )
    {
      var pixelUV = uv * image.GetSize(); 
      var lowUV = pixelUV.FloorToInt().Max( 0 );
      var highUV = ( lowUV + Vector2I.One ).Min( image.GetSize() - Vector2I.One );

      var mix = pixelUV - lowUV;

      var xTop = ColorX.Lerp( image.GetPixel( lowUV.X, lowUV.Y, mode ), image.GetPixel( highUV.X, lowUV.Y, mode ), mix.X );
      var xLow = ColorX.Lerp( image.GetPixel( highUV.X, lowUV.Y, mode  ), image.GetPixel( highUV.X, highUV.Y, mode ), mix.X );

      return ColorX.Lerp( xTop, xLow, mix.Y );            
    }
  }
}