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

namespace Rokojori
{ 
  [Tool]
  [GlobalClass]
  public partial class VertexUVSource:UVSource
  { 
    [Export]
    public VertexTransformSpace space;
    
    [Export]
    public VertexSwizzleType dimensions;

    [Export]
    public bool useDimensionsOffset = false;

    [Export]
    public VertexSwizzleType dimensionsOffset;

    [Export]
    public string sizeCustomName;

     [Export]
    public string centerCustomName;

    public override List<ShaderCode> GetUV( ShaderGenerationContext context, string target, int offsetIndex )
    { 
      var size = sizeCustomName == null || sizeCustomName == "" ? "vertexUVSourceSize" : sizeCustomName;
      var center = centerCustomName == null || centerCustomName == "" ? "vertexUVSourceCenter" : centerCustomName;

      
      var suffix = offsetIndex == 0 ? "" : ( "_" + ( offsetIndex + 1 ) );

      size += suffix;
      center += suffix;

      if ( ShaderPhase.Includes == context.phase )
      {
        return ShaderGenerationModule.IncludeUVLibrary().Concat( IncludeTransformLibrary() );
      }
      else if ( ShaderPhase.Variables == context.phase )
      {
        var uniforms = 
        @$"

        uniform vec2 {size};
        uniform vec2 {center};

        ";

        return ShaderGenerationModule.ToCode( uniforms.Indent( "" ) );
      }

      if ( ShaderPhase.Vertex != context.phase )
      {
        return null;
      }

      var member = ( dimensions + "" ).ToLower();
      var offset = " + vertex." + ( dimensionsOffset + "" ).ToLower();

      if ( ! useDimensionsOffset )
      {
        offset = "";
      }
      var vertex = "VERTEX";

      if ( VertexTransformSpace.World == space )
      {
        vertex = "localToWorld( VERTEX, MODEL_MATRIX )";
      } 
      else if ( VertexTransformSpace.View == space )
      {
        vertex = "localToView( VERTEX, MODELVIEW_MATRIX )";
      }


      var code = 
      @$"

      {{
      vec3 vertex = {vertex}; 
      {target} = mapUV( vertex.{member}{offset}, {size}, {center} ); 

      }}
      
      ";

      return ShaderGenerationModule.ToCode( code.Indent( "  ") );
    }
  }
}