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



namespace Rokojori
{
  [Tool]
  [GlobalClass]
  public partial class _XX_BakingPass:Resource
  {
    [Export]
    public bool isEnabled = true;

    public _XX_BakingPass()
    {
      CreateBakingOutputs();
    }

    protected virtual bool KeepsOriginalState()
    {
      return false;
    }

    protected virtual bool KeepsCompositors()
    {
      return false;
    }

    protected virtual void CreateBakingOutputs()
    {

    } 

    protected virtual async Task _Bake()
    {
      return;
    } 


    public async Task Bake() 
    {
      if ( bakingOutputs == null || bakingOutputs.Length == 0 )
      {
        CreateBakingOutputs();
      }

      await _Bake();

      if ( ! KeepsOriginalState() )
      {
        textureBaker.multiBaker.SetTargetDirty();
      }

      if ( ! KeepsCompositors() )
      {
        textureBaker.multiBaker.SetCompositorsDirty();
      }

      return;
    }
    
    public async Task<Texture2D> GrabDilatedTexture( bool srgb, bool alpha, bool mipmaps = true )
    {
      var texture = await textureBaker.multiBaker.GrabDilatedTexture( srgb, alpha, mipmaps );
      return texture;
    }

    public _XX_MultiTextureBaker textureBaker;

    public MultiBaker multiBaker => textureBaker.multiBaker;

    [Export]
    public BakingOutput[] bakingOutputs = [];

    public static Texture2D Get( List<_XX_BakingPass> passes, params BakingTargetType[] bakingTargetType )
    {
      for ( int i = 0 ; i < bakingTargetType.Length; i++ )
      {
        var t = Get( passes, bakingTargetType[ i ] );

        if ( t != null )
        {
          return t;
        } 
      }

      return null;
    }

    protected void Clear( BakingTargetType type, string customType = null )
    {
      Set( type, customType, null );
    }

    protected void Set( BakingTargetType type, Texture2D texture2D )
    {
      var index = Array.Find( bakingOutputs, b => b.IsType( type, null ) );

      if ( index == null )
      {
        return;
      }

      index.bakedTexture = texture2D;
    }

    protected void Set( BakingTargetType type, string customType, Texture2D texture2D )
    {
      var index = Array.Find( bakingOutputs, b => b.IsType( type, customType ) );

      if ( index == null )
      {
        return;
      }

      index.bakedTexture = texture2D;
    }

    public static Texture2D Get( List<_XX_BakingPass> passes, string customType = null )
    {
      return Get( passes, BakingTargetType.Custom, customType );
    }

    public static Texture2D Get( List<_XX_BakingPass> passes, BakingTargetType bakingTargetType, string customType = null )
    {

      var pass = passes.Find( p => p.ContainsBakingOutput( bakingTargetType ) );

      if ( pass == null )
      {
        return null;
      }

      var output = Array.Find( pass.bakingOutputs, p => p.IsType( bakingTargetType, customType ) );

      if ( output == null )
      {
        return null;
      }

      return output.bakedTexture;
    } 


    public bool ContainsBakingOutput( BakingTargetType bakingTargetType, string customType = null )
    {
      for ( int i = 0; i < bakingOutputs.Length; i++ )
      {
        if ( bakingOutputs[ i ].bakingTarget.type == bakingTargetType )
        {
          if ( bakingTargetType == BakingTargetType.Custom )
          {
            return customType == bakingOutputs[ i ].bakingTarget.customType;
          }

          return true;
        }
      }

      return false;
    }
  }
}