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

namespace Rokojori
{ 
  [Tool]
  [GlobalClass]
  public partial class ShaderGenerationModule:Resource
  { 
    public virtual List<string> GetVariantNames()
    {
      return new List<string>(){ "" };
    }

    public virtual List<ShaderCode> GetCode( ShaderGenerationContext context )
    {
      return new List<ShaderCode>(){};
    } 

    public List<ShaderCode> ToCode( params string[] values )
    {
      return Lists.From( (ShaderCode)new StringShaderCode( Lists.From( values ).Join( "" ) ) );
    }

    public List<ShaderCode> ToCode( string value )
    {
      return Lists.From( (ShaderCode)new StringShaderCode( value ) );
    } 

    public List<ShaderCode> AsUniformGroup( string name, string value )
    {
      var wideName = RegexUtility.UpperCaseAndWide( name );
      var blockCode = value.Indent( "      ", false );
            
      var code =
      @$"      
      // [ {wideName} ] 
      group_uniforms {name}; 

      {blockCode}
      
      group_uniforms;      
      ";

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

    public List<ShaderCode> ToInnerBlock( string name, string block )
    {
      var wideName = RegexUtility.UpperCaseAndWide( name );
      var blockCode = block.Indent( "      ", false );
      
      var code =
      
      @$"

      // [ {wideName} ]

      {blockCode}

      ";

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

    public List<ShaderCode> ToCode( List<string> values )
    {
      return Lists.From( (ShaderCode)new StringShaderCode( Lists.From( values ).Join( "" ) ) );
    }

    public string Uniform( Vector2Property property )
    {
      var name = property.propertyName.propertyName;
      var x = property.value.X._G();
      var y = property.value.Y._G();

      return @$"uniform vec2 {name} = vec2( {x}, {y});";
    }

    public string Uniform( string name, float value )
    {
      return @$"uniform float {name} = {value._G()};";
    }

    public string Uniform01( string name, float value )
    {
      return Uniform( name, value, 0, 1 );
    }

    public string Uniform( string name, float value, float min, float max )
    {
      var mi = min._G();
      var ma = max._G();
      var v  = value._G();

      return @$"uniform float {name}:hint_range( {mi}, {ma}) = {v};";
    }

    public string UniformSampler( string name, string hints )
    {
      return @$"uniform sampler2D {name}:{hints};";
    }

    public string Uniform( string name, Color color )
    {
      var r = color.R._G();
      var g = color.G._G();
      var b = color.B._G();
      var a = color.A._G();

      return @$"uniform vec4 {name}:source_color = vec4( {r}, {g}, {b}, {a});";
    
    }

    public string Uniform( string name, Vector3 vec )
    {
      var x = vec.X._G();
      var y = vec.Y._G();
      var z = vec.Z._G();

      return @$"uniform vec3 {name} = vec3( {x}, {y}, {z});";    
    }

    public string Uniform( string name, Vector4 vec )
    {
      var x = vec.X._G();
      var y = vec.Y._G();
      var z = vec.Z._G();
      var w = vec.W._G();

      return @$"uniform vec4 {name} = vec4( {x}, {y}, {z}, {w});";    
    }
  }

}