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

namespace Rokojori
{ 
  [Tool]
  [GlobalClass]
  public partial class FloatPropertyName : ShaderPropertyName
  { 
    public override RenderingServer.GlobalShaderParameterType GetParameterType()
    {
      return RenderingServer.GlobalShaderParameterType.Float;
    }

    public bool isComponent
    {
      get 
      {
        if ( propertyName == null || propertyName.Length < 3 )
        {
          return false;
        } 

        if ( propertyName[ propertyName.Length - 2 ] != '.' )
        {
          return false;
        }

        var lastCharacter = propertyName[ propertyName.Length - 1 ] + "";

        return "xyzwrgba".IndexOf( lastCharacter.ToLower() ) != -1;
      }
    }

    string GetComponentParentName()
    {
      if ( ! isComponent )
      {
        return propertyName;
      }

      return propertyName.Substring( 0, propertyName.Length - 2 );
    }

    int componentIndex
    {
      get 
      {
        if ( ! isComponent )
        {
          return -1;
        }

        var lastCharacter = ( propertyName[ propertyName.Length - 1 ] + "" ).ToLower();
        
        return Mathf.Max( "xyzw".IndexOf( lastCharacter ), "rgba".IndexOf( lastCharacter ) );
      }
    }





    public void Set( Material material, float value )
    {
      if ( isComponent )
      {
        var member = Shaders.GetUniformMemberByName( material, GetComponentParentName() );

        if ( member == null )
        {
          return;
        }

        var materialValue = member.Get<Variant>( material );

        if ( Variant.Type.Vector2 == materialValue.VariantType )
        {
          var v2 = materialValue.AsVector3();
          v2[ componentIndex ] = value;
          member.Set( material, v2 );
        }
        else if ( Variant.Type.Vector3 == materialValue.VariantType )
        {
          var v3 = materialValue.AsVector3();
          v3[ componentIndex ] = value;
          member.Set( material, v3 );
        }
        else if ( Variant.Type.Vector4 == materialValue.VariantType )
        {
          var v4 = materialValue.AsVector4();
          v4[ componentIndex ] = value;
          member.Set( material, v4 );
        }
        else if ( Variant.Type.Color == materialValue.VariantType )
        {
          var color = materialValue.AsColor();
          color[ componentIndex ] = value;
          member.Set( material, color );
        }

        return;

        
      }
      
      _Set( material, value );
      
    
    }

    public float Get( Material material )
    {
      if ( isComponent )
      {
        var member = Shaders.GetUniformMemberByName( material, GetComponentParentName() );

        if ( member == null )
        {
          return 0;
        }

        var materialValue = member.Get<Variant>( material );

        if ( Variant.Type.Vector2 == materialValue.VariantType )
        {
          var v2 = materialValue.AsVector3();
          return v2[ componentIndex ];
        }
        else if ( Variant.Type.Vector3 == materialValue.VariantType )
        {
          var v3 = materialValue.AsVector3();
          return v3[ componentIndex ];
        }
        else if ( Variant.Type.Vector4 == materialValue.VariantType )
        {
          var v4 = materialValue.AsVector4();
          return v4[ componentIndex ];
        }
        else if ( Variant.Type.Color == materialValue.VariantType )
        {
          var color = materialValue.AsColor();
          return color[ componentIndex ];
        }

        
      }

      return _Get( material, 0f );
    }

    public static FloatPropertyName Create( string name )
    {
      var fp = new FloatPropertyName(); 
      fp.propertyName = name;
      return fp;
    }
  }
}