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

namespace Rokojori
{ 
  [Tool]
  [GlobalClass]
  public partial class SubMaterialTransfer:Resource
  { 
    [Export]
    public string info;

    [ExportGroup("Shader Matching/Standard Shaders")]
    [Export]
    public bool canvasItem;
    [Export]
    public bool fog;
    [Export]
    public bool orm3D;
    [Export]
    public bool standard3D;
    [Export]
    public bool panoramaSky;
    [Export]
    public bool particleProcess;
    [Export]
    public bool physicalSky;
    [Export]
    public bool placeholder;
    [Export]
    public bool proceduralSky;
    [Export]
    public bool shader;

    [ExportGroup("Shader Matching/Custom Shaders")]
    [Export]
    public Shader[] shaders = new Shader[ 0 ];
    
    
    public bool MatchesMaterial( Material m )
    {
      if ( TypeTest<CanvasItemMaterial>( m, canvasItem ) ){ return true; }
      if ( TypeTest<FogMaterial>( m, fog ) ){ return true; }
      if ( TypeTest<OrmMaterial3D>( m, orm3D ) ){ return true; }
      if ( TypeTest<StandardMaterial3D>( m, standard3D ) ){ return true; }

      if ( TypeTest<PanoramaSkyMaterial>( m, panoramaSky ) ){ return true; }
      if ( TypeTest<ParticleProcessMaterial>( m, particleProcess ) ){ return true; }
      if ( TypeTest<PhysicalSkyMaterial>( m, physicalSky ) ){ return true; }
      if ( TypeTest<PlaceholderMaterial>( m, placeholder ) ){ return true; }

      if ( TypeTest<ProceduralSkyMaterial>( m, proceduralSky ) ){ return true; }
      if ( TypeTest<ShaderMaterial>( m, shader ) ){ return true; }

      var shaderMaterial = m as ShaderMaterial;

      if ( shaderMaterial == null )
      {
        return false;
      }

      for ( int i = 0; i < shaders.Length; i++ )
      {
        if ( shaderMaterial.Shader == shaders[ i ] )
        {
          return true;
        }
      }

      return false;
    }

    bool TypeTest<T>( Material m, bool isType ) where T:class
    {
      if ( ! isType )
      {
        return false;
      }

      return ( m as T ) != null;
    }

    [ExportGroup("Property Transfers")]
    [Export]
    public BoolPropertyTransfer[] bools = new BoolPropertyTransfer[ 0 ];

    [Export]
    public ColorPropertyTransfer[] colors = new ColorPropertyTransfer[ 0 ];

    [Export]
    public FloatPropertyTransfer[] floats = new FloatPropertyTransfer[ 0 ];

    [Export]
    public IntPropertyTransfer[] ints = new IntPropertyTransfer[ 0 ];

    [Export]
    public Texture2DPropertyTransfer[] texture2D = new Texture2DPropertyTransfer[ 0 ];

    [Export]
    public Vector2PropertyTransfer[] vector2 = new Vector2PropertyTransfer[ 0 ];

   [Export]
    public Vector3PropertyTransfer[] vector3 = new Vector3PropertyTransfer[ 0 ];

    [Export]
    public Vector4PropertyTransfer[] vector4 = new Vector4PropertyTransfer[ 0 ];

    [Export]
    public CustomMaterialTransfer[] custom = new CustomMaterialTransfer[ 0 ];

    
    public void Transfer( Material a, Material b )
    {
      Arrays.ForEach( bools, p => p.Transfer( a, b ) );
      Arrays.ForEach( colors, p => p.Transfer( a, b ) );
      Arrays.ForEach( floats, p => p.Transfer( a, b ) );
      Arrays.ForEach( ints, p => p.Transfer( a, b ) );
      Arrays.ForEach( texture2D, p => p.Transfer( a, b ) );
      Arrays.ForEach( vector2, p => p.Transfer( a, b ) );
      Arrays.ForEach( vector3, p => p.Transfer( a, b ) );
      Arrays.ForEach( vector4, p => p.Transfer( a, b ) );
    }


  }
}

