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

namespace Rokojori
{ 
  public enum SpatialMaskFormulaType
  { 
    Multiply,
    Add,
    Custom    
  }

  public static class SpatialMaskFormulaTypeUtility
  {
    public static string GetCombiningCode( 
      SpatialMaskFormulaType maskFormula, string customMaskFormula, 
      string combinedMaskName, string contextPrefix, int numMasks 
    )
    {
      var combiningCode = $"float {combinedMaskName} = ";

      if ( numMasks == 0 )
      {
        combiningCode += "1.0";
      }

      if ( SpatialMaskFormulaType.Add == maskFormula || SpatialMaskFormulaType.Multiply == maskFormula )
      {
        var op = SpatialMaskFormulaType.Add == maskFormula ? " + " : " * ";

        for ( int i = 0; i < numMasks; i++ )
        {
          var maskName = $"{contextPrefix}Mask{i}";

          combiningCode += maskName;

          if ( i != ( numMasks - 1 ) ) 
          {
            combiningCode += op;
          }
        }
        
      }
      else
      {
        var replacedFormula = customMaskFormula;

        for ( int i = 0; i < numMasks; i++ )
        {
          var maskName = $"{contextPrefix}Mask{i}";
          replacedFormula = replacedFormula.Replace( "_m" + i + "_", maskName );
        }
      }

      return combiningCode;
    }

    public static List<ShaderCode> GetFragmentMaskCode( 
      ShaderGenerationContext context, 
      SpatialMaskFormulaType type, string formula, 
      SpatialMask[] masks, 
      string contextPrefix, string combinedMaskName 
    )
    {
      var list = new List<ShaderCode>();
      var maskIndex = 0;

      masks.ForEach(
        ( m )=>
        {
          var maskName = $"{contextPrefix}Mask{maskIndex}";
          list.Add( ShaderGenerationModule.ToCode( $"  float {maskName} = 0.0;\n" ) );
          list.Add( ShaderGenerationModule.ToCode( $"  {{\n" ) );
          var maskCode = m.GetMaskCode( context, contextPrefix, maskName );
          if ( maskCode != null )
          {
            list.Add( maskCode );
          }

          list.Add( ShaderGenerationModule.ToCode( $"  }}\n" ) );
          maskIndex++;
        }
      );  

      var combiningCode = GetCombiningCode( type, formula, combinedMaskName, contextPrefix, masks.Length ); 

     
      combiningCode += ";\n";
      

      list.Add( ShaderGenerationModule.ToCode( combiningCode.Indent( "  " ) ) ); 
      
      return list;
    }

  }
}