
using Godot;
using Godot.Collections;
using System.Threading.Tasks;

namespace Rokojori
{  
  [Tool]
  [GlobalClass]
  public partial class DefaultPostProcessingModule: FeatureModule
  { 
    [Export]
    public bool ao = true;

    [Export]
    public bool ssil = true;

    [Export]
    public bool glow = true;

    [Export]
    public bool fog = true;

    [Export]
    public bool adjustments = true;

    [Export]
    public Environment.ToneMapper toneMapping = Environment.ToneMapper.Filmic;

    [Export]
    public bool postFX = true;

    public override async Task ProcessPass( PresetContext presetContext )
    {
      if ( PresetPass.Prefly == presetContext.pass )
      {
        if ( AppPreset.PresetErrorHandlingMode.Automatic_Fix == presetContext.appPreset.errorHandling )
        {
          presetContext.appPreset.mainModule.worldEnvironment = true;
        }
      }
      else if ( PresetPass.Process == presetContext.pass )
      {
        var environment = presetContext.root.Get<WorldEnvironment>();
        SetupPostProcessing( environment );
      }

      return;
    }
     
    void SetupPostProcessing( WorldEnvironment worldEnvironment )
    {
      var env = worldEnvironment.Environment;

      if ( ao )
      {
        env.SsaoEnabled = true;
        env.SsaoAOChannelAffect = 1;
        env.SsaoLightAffect = 1;
        env.SsaoIntensity = 2.5f;
      }

      if ( ssil )
      {
        env.SsilEnabled = true;
        env.SsilRadius = 2.5f;
        env.SsilIntensity = 2;
        env.SsilNormalRejection = 0.5f;
      }

      if ( glow )
      {
        env.GlowEnabled = true;

        for ( int i = 0; i < 7 ; i++ )
        {
          var value =  i == 0 ? 4 : i == 1 ? 8 : Mathf.Pow( 2, 6 - i );
          env.SetGlowLevel( i, value );
        }
        env.GlowNormalized = true;
        env.GlowIntensity = 1f;
        env.GlowBlendMode = Environment.GlowBlendModeEnum.Screen;
      }

      if ( fog )
      {
        env.FogEnabled = true;
        env.FogLightColor = new Color( 160f/255f, 169f/255f, 174f/255f );
        env.FogSunScatter = 0.5f;
        env.FogAerialPerspective = 0.5f;
        env.FogSkyAffect = 0f;
        env.FogDensity = 0.005f;
      }

      if ( adjustments )
      {
        env.AdjustmentEnabled = true;
        env.AdjustmentContrast = 0.9f;
        env.AdjustmentSaturation = 1.1f;
      }
      
      env.TonemapMode = toneMapping;

      if ( Environment.ToneMapper.Filmic == env.TonemapMode )
      {
        env.TonemapExposure = 1.5f;
        env.TonemapWhite = 1.5f;
      }

      if ( postFX )
      {
        if ( worldEnvironment.Compositor == null )
        {
          worldEnvironment.Compositor =new Compositor();
        }

        var compositor = worldEnvironment.Compositor;

        var vignette = new VignetteEffect();
        vignette.amount = 0.5f;

        // var chromaticAberation = new ChromaticAberation();

        // var temporalSmear = new TemporalSmearEffect();
        // temporalSmear.amount = 0.1f;
        // temporalSmear.smearingFrames = 6;
        
        var array = new Godot.Collections.Array<CompositorEffect>();
        // array.AddRange( [vignette, chromaticAberation, temporalSmear ]);
        array.AddRange( [vignette ]);
        compositor.CompositorEffects = array;
      }
    }
  }
}