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

namespace Rokojori
{ 
  public class UniformMember
  {
    public string name;
    public Variant.Type type;

    public PropertyHint hint;
    public string hintString;
    public int usage;

    public override string ToString()
    {
      return type + " " + name + "( '" + hint + "', '" +  hintString + "', '" + usage + "')";
    }

    public bool Equals( UniformMember other )
    {
      if ( other == null )
      {
        return false;
      }

      return name == other.name &&
             type == other.type &&
             hint == other.hint &&
             hintString == other.hintString &&
             usage == other.usage 
      ;
    }

    public static UniformMember Create( string name, Variant.Type type )
    {
      var um  = new UniformMember();
      um.name = name;
      um.type = type;
      return um;
    }

    public string GetPropertyNameType()
    {
      if ( type == Variant.Type.Object )
      {
        return ( hintString + "" );
      }
      else
      {
        return ( type + "" );
      }
    }

    public T Get<[MustBeVariant] T>( Material material )
    {
      return material is ShaderMaterial sm ? Get<T>( sm ) : Get<T>( (StandardMaterial3D) material );
    }

    public T Get<[MustBeVariant] T>( ShaderMaterial shaderMaterial )
    {
      return shaderMaterial.GetShaderParameter( name ).As<T>();
    }

    public T Get<[MustBeVariant] T>( StandardMaterial3D standardMaterial )
    {
      var property = new GetSetShaderPropertyName();
      property.propertyName = name;
      return property._Get<T>( standardMaterial, default( T ) );
    }

    public void Set( ShaderMaterial shaderMaterial, Variant value )
    {
      shaderMaterial.SetShaderParameter( name, value );
    }

    public void Set( StandardMaterial3D standardMaterial, Variant value )
    {
      var property = new GetSetShaderPropertyName();
      property.propertyName = name;
      property._Set<Variant>( standardMaterial, value );
    }

    public void Set( Material material, Variant value )
    {
      if ( material is ShaderMaterial sm )
      {
        Set( sm, value );
      }
      else
      {
        Set( (StandardMaterial3D) material, value );
      }
    }

  }
}