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

namespace Rokojori
{ 
  [Tool]
  [GlobalClass]
  public partial class AlbedoModule:TextureModule
  { 
    public AlbedoModule()
    {
      SetDomainNames( "albedo" );
      
      _target = "ALBEDO";
      _srgb = true;
      _type = TextureChannelType.RGB;
      scaleType = TextureChannelType.RGB;
    }



    [Export]
    public TextureFilter filter = TextureFilter.Linear_MipMap_Anisotropic;

    [Export]
    public bool useTint = true;

    [Export]
    public bool srgb = true;

    [Export]
    public bool writeAlpha = false;

    [Export]
    public bool repeat = true;

    [Export]
    public string tintVarying = "";

    [Export]
    public string uvChannel = "UV";

    [Export]
    public TextureDefault textureDefault = TextureDefault.White;

    [Export]
    public AssignmentType assignmentType = AssignmentType.Set;   

    [Export]
    public AlbedoOverlayLayer[] overlayLayers = [];

    
    public override void GrabValues()
    {
      _domainMode = useTint ? DomainMode.Texture_Scale : DomainMode.Texture;
      _textureFilter = filter;
      _srgb = srgb;
      _repeat = repeat;
      _textureDefault = textureDefault;
      _uvChannel = uvChannel;

      _assignmentType = assignmentType;
      
    }

    public override List<ShaderVariant> GetVariants( ShaderGenerationContext context )
    {
      var variants = base.GetVariants( context );

      

      if ( ShaderPhase.Fragment == context.phase )
      {
        if ( tintVarying != null && tintVarying != "" )
        {
          var tinting = $"ALBEDO *= {tintVarying}.rgb;\n";
          variants = ShaderVariant.CombineVariants( variants, ToVariants( ToCode( tinting ) ) );
        }

        if ( writeAlpha )
        {
          var value = GetSampledName() + ".a" ;

          if ( useTint )
          {
            value += " * albedo.a";
          }

          if ( tintVarying != null && tintVarying != "" )
          {
            value += $" * {tintVarying}.a";
          }

          var assignment = "  ALPHA *= " + value + ";\n\n";
          variants = ShaderVariant.CombineVariants( variants, ToVariants( ToCode( assignment ) ) );
        }
      }

      if ( overlayLayers != null )
      {
        overlayLayers.ForEach(
          ( layer )=>
          {
            var layerName = "albedo" + ( overlayLayers.IndexOf( layer ) + 2 );
            var uniformGroup = "albedo" + ( overlayLayers.IndexOf( layer ) + 2 );
            layer.uniformGroup = uniformGroup; 
            var shaderCode = layer.GetOverlayCode( context, layerName, "ALBEDO", "ALBEDO" );

            if ( shaderCode == null )
            {
              return;
            }

            variants = ShaderVariant.CombineVariants( variants, ToVariants( shaderCode ) );
          }
        );
      }

      return variants;  

    }

    
  }
}