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



namespace Rokojori
{
  [Tool]
  [GlobalClass]
  public partial class PointMeshBaker:Node
  {
    [Export]
    public Texture2D albedo;

    [Export]
    public Texture2D normal;

    [Export]
    public MeshInstance3D output;

    [Export]
    public int pixelsX;
    
    [Export]
    public int pixelsY;

    [Export]
    public Vector2 pivot;
    
    [Export]
    public Vector3 offset;

    [Export]
    public Vector3 scale;

    [ExportToolButton( "Bake")]
    public Callable BakeButton => Callable.From( () => 
    {
      BakePointMesh();
    } 
    );

    public void BakePointMesh()
    { 
      var mg = new MeshGeometry( true, false, true, false );
      mg.customMeshAttributes.Add( new MeshAttributeVector4List( 0 ) );
      mg.normals = null;

      var albedoImage = albedo.GetImage();
      var normalImage = normal.GetImage();

      var index = 0;

      for ( int x = 0; x < pixelsX; x++ )
      {
        for ( int y = 0; y < pixelsY; y++ )
        {
          var fx = x / (float) pixelsX;
          var fy = 1f - y / (float) pixelsY;

          var position = new Vector3( fx - pivot.X, fy - pivot.Y, 0 )  * scale + offset;        

          var colorPosX = Mathf.FloorToInt( fx * albedoImage.GetSize().X );  
          var colorPosY = Mathf.FloorToInt( fy * albedoImage.GetSize().Y );  
          var color = albedoImage.GetPixel( colorPosX, colorPosY );

          var normalPosX = Mathf.FloorToInt( fx * normalImage.GetSize().X );  
          var normalPosY = Mathf.FloorToInt( fy * normalImage.GetSize().Y ); 
          var normal = normalImage.GetPixel( normalPosX, normalPosY );

          mg.AddPoint( position, color.SRGBtoLinear(), normal.SRGBtoLinear().ToVector3() * 2.0f - Vector3.One, 0 );

          // this.LogInfo( "Created point at:", index, position );

          index ++;
        }
      }

      output = output == null ? this.CreateChild<MeshInstance3D>() : output;

      output.Mesh = mg.GenerateMesh( Mesh.PrimitiveType.Points, null, false );
    } 
  }
}