using Godot;

namespace Rokojori
{  
  [Tool]
  [GlobalClass]
  public partial class EllipseFlareType:FlareType
  {
    public override Shader GetShader( FlareLayer.Data data )
    {
      var bm = data.GetBlendMode();

      if ( FlareBlendMode.BlendModeType.Add == bm )
      {
        return EllipseTypeFlareAddShader.shader.Get();
      }

      if ( FlareBlendMode.BlendModeType.Mix == bm )
      {
        return EllipseTypeFlareMixShader.shader.Get();
      }

      if ( FlareBlendMode.BlendModeType.Subtract == bm )
      {
        return EllipseTypeFlareSubtractShader.shader.Get();
      }

      if ( FlareBlendMode.BlendModeType.Multiply == bm )
      {
        return EllipseTypeFlareMultiplyShader.shader.Get();
      }

      return null;
      
    }

    public override ShaderMaterial CreateMaterial( FlareLayer.Data data )
    {
      var bm = data.GetBlendMode();

      if ( FlareBlendMode.BlendModeType.Add == bm )
      {
        return new EllipseTypeFlareAddMaterial();
      }

      if ( FlareBlendMode.BlendModeType.Mix == bm )
      {
        return new EllipseTypeFlareMixMaterial();
      }

      if ( FlareBlendMode.BlendModeType.Subtract == bm )
      {
        return new EllipseTypeFlareSubtractMaterial();
      }

      if ( FlareBlendMode.BlendModeType.Multiply == bm )
      {
        return new EllipseTypeFlareMultiplyMaterial();
      }

      return null;
    }

    [ExportGroup( "Main")]

    [Export]
    public float shapeScaleRange = 1f;

    [Export(PropertyHint.Range, "0,1")]
    public float shapeScale = 1f;

    [Export]
    public float fillMultiply = 1f;

    [Export]
    public float fillAdd = 0f;

    [Export]
    public float maskMultiply = 1f;

    [Export]
    public float maskAdd = 0f;

    [ExportGroup( "Radial Fill", "radialFill")]
    [Export]
    public Texture2D radialFillTexture;
    [Export]
    public float radialFillStrength = 1f;
    [Export]
    public float radialFillTile = 1f;
    [Export]
    public float radialFillOffset = 1f;
    [Export]
    public bool radialFillRepeat = false;

    [ExportGroup( "Conic Fill", "conicFill")]
    [Export]
    public Texture2D conicFillTexture;
    [Export]
    public float conicFillStrength = 1f;
    [Export]
    public float conicFillTile = 1f;
    [Export]
    public float conicFillOffset = 1f;
    [Export]
    public bool conicFillRepeat = false;

    [ExportGroup( "Radial Mask", "radialMask")]
    [Export]
    public Texture2D radialMaskTexture;

    [Export]
    public float radialMaskStrength = 1f;
    [Export]
    public float radialMaskTile = 1f;
    [Export]
    public float radialMaskOffset = 1f;
    [Export]
    public bool radialMaskRepeat = false;

    [ExportGroup( "Conic Mask", "conicMask")]
    [Export]
    public Texture2D conicMaskTexture;

    [Export]
    public float conicMaskStrength = 1f;
    [Export]
    public float conicMaskTile = 1f;
    [Export]
    public float conicMaskOffset = 1f;
    [Export]
    public bool conicMaskRepeat = false;


    [ExportGroup( "Noise","noise")]
    [Export( PropertyHint.Range, "0,1" ) ]
    public float noiseAmount = 0;

    [Export( PropertyHint.Range, "0.1,100" ) ]
    public float noiseScale = 0;

    public void SetValues( Material material, 
                         Sampler2DPropertyName texture, Texture2D tex,
                         FloatPropertyName str, float strValue,
                         FloatPropertyName tile, float tileValue,
                         FloatPropertyName off, float offValue,
                         BoolPropertyName repeat, bool repeatValue 
    )
    { 
      texture.Set( material, tex );
      str.Set( material, strValue );
      tile.Set( material, tileValue );
      off.Set( material, offValue );
      repeat.Set( material, repeatValue );
    }


    public override void ApplyShape( FlareLayer.Data data )
    {
      var material = data.material;

      EllipseTypeFlareAddShader.shapeScale.Set( material, shapeScale * shapeScaleRange );

      EllipseTypeFlareAddShader.fillMultiply.Set( material, fillMultiply );
      EllipseTypeFlareAddShader.fillAdd.Set( material, fillAdd );
      EllipseTypeFlareAddShader.maskMultiply.Set( material, maskMultiply );
      EllipseTypeFlareAddShader.maskAdd.Set( material, maskAdd );

      SetValues( material, 
        EllipseTypeFlareAddShader.radialFill, radialFillTexture,
        EllipseTypeFlareAddShader.radialFillStrength, radialFillStrength,
        EllipseTypeFlareAddShader.radialFillTile, radialFillTile,
        EllipseTypeFlareAddShader.radialFillOffset, radialFillOffset,
        EllipseTypeFlareAddShader.radialFillRepeat, radialFillRepeat
      );

      SetValues( material, 
        EllipseTypeFlareAddShader.conicFill, conicFillTexture,
        EllipseTypeFlareAddShader.conicFillStrength, conicFillStrength,
        EllipseTypeFlareAddShader.conicFillTile, conicFillTile,
        EllipseTypeFlareAddShader.conicFillOffset, conicFillOffset,
        EllipseTypeFlareAddShader.conicFillRepeat, conicFillRepeat
      );

      SetValues( material, 
        EllipseTypeFlareAddShader.radialMask, radialMaskTexture,
        EllipseTypeFlareAddShader.radialMaskStrength, radialMaskStrength,
        EllipseTypeFlareAddShader.radialMaskTile, radialMaskTile,
        EllipseTypeFlareAddShader.radialMaskOffset, radialMaskOffset,
        EllipseTypeFlareAddShader.radialMaskRepeat, radialMaskRepeat
      );

      SetValues( material, 
        EllipseTypeFlareAddShader.conicMask, conicMaskTexture,
        EllipseTypeFlareAddShader.conicMaskStrength, conicMaskStrength,
        EllipseTypeFlareAddShader.conicMaskTile, conicMaskTile,
        EllipseTypeFlareAddShader.conicMaskOffset, conicMaskOffset,
        EllipseTypeFlareAddShader.conicMaskRepeat, conicMaskRepeat
      );

      BaseFlareShader.shapeNoiseAmount.Set( material, noiseAmount );
      BaseFlareShader.shapeNoiseScale.Set( material, noiseScale );

    }
  }
}
