using System.Collections;
using System.Collections.Generic;
using Godot;
using System;
using System.Threading.Tasks;



namespace Rokojori
{
  [Tool]
  [GlobalClass]
  public partial class UVBakingPass: _XX_BakingPass
  {
    public UVBakingPass():base(){}

    protected override void CreateBakingOutputs()
    {
      bakingOutputs = [ BakingOutput.UV() ];
    }

    protected override bool KeepsOriginalState()
    {
      return false;
    }

    protected override bool KeepsCompositors()
    {
      return true;
    }

    protected override async Task _Bake() 
    {
      Clear( BakingTargetType.UV );

      SetMaterial();

      await multiBaker.RequestNextFrame();

      var texture = await GrabDilatedTexture( false, false );

      Set( BakingTargetType.UV, texture );

      return;
    }

    public void SetMaterial()
    {
      Dictionary<Material,Material> materials = new Dictionary<Material, Material>();

      Nodes.ForEach<Node3D>( multiBaker.X_bakingTargetContainer,
        ( n )=>
        {
          SetMaterial( n, materials );
        }
      );
    }
    
    public static readonly CachedResource<Shader> shader = new CachedResource<Shader>( 
      "res://addons/rokojori_action_library/Runtime/Shading/Shaders/Baking/UVBaker.gdshader"
    );  


    void SetMaterial( Node3D n, Dictionary<Material,Material> materials )
    {
      var material = Materials.Get<Material>( n );

      if ( material == null )
      {
        // n.LogInfo( "No material found" );
        return;
      }

      if ( ! materials.ContainsKey( material ) )
      {
        var appliedMaterial = new ShaderMaterial();
        appliedMaterial.Shader = shader.Get();
      
        if ( material is StandardMaterial3D sm )
        {
          // n.LogInfo( "StandardMaterial3D found" );

          appliedMaterial.SetShaderParameter( "uv1_scale", sm.Uv1Scale );
          appliedMaterial.SetShaderParameter( "uv1_offset", sm.Uv1Offset );
          
        }
        else
        {
          // n.LogInfo( "No StandardMaterial3D found", material.GetType().Name );
        }

        
        materials[ material ] = appliedMaterial;
      }

      
      Materials.Set( n, materials[ material ] );
    }

  }
}