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

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

    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 windMaxStrength = 1;
        uniform float windMaxRotation = 1;
        uniform float windStrengthCurve:hint_range(0,1) = 0.5f;
        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;
        global uniform sampler2D rj_GlobalWindNoiseTexture;
        global uniform vec2 rj_GlobalWindPosition;
        global uniform vec2 rj_GlobalWindDirection;
        global uniform float rj_GlobalWindSpeed;   
        varying float vertexWindAO;
        "
          
        );
           
      }

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

        return ToInnerBlock( "Wind",
          
        @"

        float cachedVertexWindAO = 0.0;

        applyGlobalWind(
          MODEL_MATRIX,
          VERTEX,
          NORMAL,
          cachedVertexWindAO,
          windOcclusionAmount,
          rj_GlobalWindNoiseTexture,
          rj_GlobalWindPosition,
          rj_GlobalWindDirection,
          rj_GlobalWindSpeed,
          windMaxStrength,
          windMaxRotation,
          windStrengthCurve,
          windStart,
          windEnd,
          windWeightCurve,
          windHeightCompensation,
          windNormalBending
        );

        vertexWindAO = cachedVertexWindAO;

        "
                  
        ) ;
      }

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

      return null;
    }
  }
}