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

namespace Rokojori
{ 
  [Tool]
  [GlobalClass]
  public partial class GeometryWind:GeometryModifier
  {   

    [Export]
    public bool sampleAngleFromNoise = true;

    [Export]
    public bool heightCompensation = true;


    public override List<ShaderCode> GetGeometryCode( ShaderGenerationContext context, int offsetIndex )
    {
      if ( offsetIndex != 0 )
      {
        throw new Exception( "Unique component, can't be used multiple times");
      }

      if ( ShaderPhase.Includes == context.phase )
      { 
        return IncludeFromLibrary( "Wind" );
      }

      if ( ShaderPhase.Variables == context.phase )
      {        
        return AsUniformGroup( "Wind",
          
        @"
        
        uniform float windStrength = 0;
        uniform vec2 windSpeed = vec2(1,1);
        uniform float windScale = 0.1;
        uniform sampler2D windNoise;
        uniform vec2 windNoiseAngleOffset;
        uniform vec2 windNoiseStrengthOffset;
        uniform float windStart = 0;
        uniform float windEnd = 1;
        uniform float windWeightCurve:hint_range(0,1) = 0.5f;
        uniform float windHeightCompensation :hint_range(0,1) = 0.5f;
        uniform float windNormalBending :hint_range(0,1) = 0.1f;
        uniform float windOcclusionAmount = 0;
        varying float vertexWindAO;
        "
          
        );
           
      }

      if ( ShaderPhase.Vertex == context.phase )
      {

        return ToInnerBlock( "Wind",
          
        @"

        float cachedVertexWindAO = 0.0;

        applyWind( 
          TIME, 
          MODEL_MATRIX, 
          VERTEX, 
          NORMAL,
          cachedVertexWindAO,
          windOcclusionAmount,
          windStrength,
          windSpeed,
          windScale,
          windNoise,
          windNoiseAngleOffset,
          windNoiseStrengthOffset,
          windStart,
          windEnd,
          windWeightCurve,
          windHeightCompensation,
          windNormalBending
        );

        vertexWindAO = cachedVertexWindAO;

        "
                  
        ) ;
      }

      if ( ShaderPhase.Fragment == context.phase ) 
      {
        return ToCode( "AO *= vertexWindAO;".Indent( "  " ).LineBreaks() );      
      }

      return null;
    }
  }
}