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

namespace Rokojori
{ 
  [Tool]
  [GlobalClass]
  public partial class TransparencyModule:ShaderGenerationModule
  { 
    [Export]
    public BaseMaterial3D.TransparencyEnum transparency = BaseMaterial3D.TransparencyEnum.Disabled;

    [ExportGroup( "Alpha Scissor")]
    [Export]
    public float alphaScissorTreshold = 0.01f;

    [ExportGroup( "")]
    [Export]
    public BaseMaterial3D.BlendModeEnum blendMode = BaseMaterial3D.BlendModeEnum.Mix;

    [Export]
    public BaseMaterial3D.CullModeEnum cullMode = BaseMaterial3D.CullModeEnum.Back;

    [Export]
    public BaseMaterial3D.DepthDrawModeEnum depthDraw = BaseMaterial3D.DepthDrawModeEnum.OpaqueOnly;

    [Export]
    public bool noDepthTest = false;

    public override List<ShaderVariant> GetVariants( ShaderGenerationContext context )
    {
      if ( ShaderPhase.Fragment == context.phase )
      {
        if ( BaseMaterial3D.TransparencyEnum.AlphaScissor == transparency )
        {
          var code = $"ALPHA_SCISSOR_THRESHOLD = {alphaScissorTreshold._G()};\n"; 
          return ToVariants( ToCode( code.Indent( "  " ) ) );
        }

        return null;
           
      }

      if ( ShaderPhase.RenderMode != context.phase )
      {
        return null;
      }

      var value = "";

      var transparencyModes = new Dictionary<BaseMaterial3D.TransparencyEnum,string>();
      transparencyModes[ BaseMaterial3D.TransparencyEnum.Disabled ] = "";
      transparencyModes[ BaseMaterial3D.TransparencyEnum.Alpha ] = "";
      transparencyModes[ BaseMaterial3D.TransparencyEnum.AlphaScissor ] = "";
      transparencyModes[ BaseMaterial3D.TransparencyEnum.AlphaHash ] = "";
      transparencyModes[ BaseMaterial3D.TransparencyEnum.AlphaDepthPrePass ] = "depth_prepass_alpha, ";

      value += transparencyModes[ transparency ];
      

      var blendModes = new Dictionary<BaseMaterial3D.BlendModeEnum,string>();
      blendModes[ BaseMaterial3D.BlendModeEnum.Mix ] = "blend_mix";
      blendModes[ BaseMaterial3D.BlendModeEnum.Add ] = "blend_add";
      blendModes[ BaseMaterial3D.BlendModeEnum.Mul ] = "blend_mul";
      blendModes[ BaseMaterial3D.BlendModeEnum.Sub ] = "blend_sub";     
      blendModes[ BaseMaterial3D.BlendModeEnum.PremultAlpha ] = "blend_premul_alpha";

      value += blendModes[ blendMode ] + ", ";

      var cullmodes = new Dictionary<BaseMaterial3D.CullModeEnum,string>();
      cullmodes[ BaseMaterial3D.CullModeEnum.Disabled ] = "cull_disabled";
      cullmodes[ BaseMaterial3D.CullModeEnum.Front ] = "cull_front";
      cullmodes[ BaseMaterial3D.CullModeEnum.Back ] = "cull_back";

      value += cullmodes[ cullMode ] + ", ";


      var depthModes = new Dictionary<BaseMaterial3D.DepthDrawModeEnum,string>();
      depthModes[ BaseMaterial3D.DepthDrawModeEnum.OpaqueOnly ] = "depth_draw_opaque";
      depthModes[ BaseMaterial3D.DepthDrawModeEnum.Always ] = "depth_draw_always";
      depthModes[ BaseMaterial3D.DepthDrawModeEnum.Disabled ] = "depth_draw_never";

      value += depthModes[ depthDraw ] + ", ";


      if ( noDepthTest )
      {
        value += "depth_test_disabled";
      }

      value = RegexUtility.Replace( value, @"\,\s*$", "" );

      return ToVariants( Lists.From( (ShaderCode) new StringShaderCode( value ) ) );      
    }


  }
}