using Godot;

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

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

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

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

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

      return null;
      
    }

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

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

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

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

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

      return null;
    }

    public enum ShapeType
    {      
      Circle,
      Cross,
      Triangle,
      Rectangle,
      Pentagon,
      Hexagon,
      Octogon,
      Hexagram,
      Pentagram,
      Ring,
      Cutout1,
      Cutout2,
      Heart      
    }

    [Export]
    public ShapeType shapeType = ShapeType.Pentagon;

    [Export( PropertyHint.Range, "-180,180" ) ]
    public float shapeRotation = 0;

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

    [ExportGroup( "Shape Opacity", "shapeOpacity")]
    [Export( PropertyHint.Range, "-2,2" ) ]
    public float shapeOpacityInnerBorder = 0f;

    [Export( PropertyHint.Range, "-2,2" ) ]
    public float shapeOpacityOuterBorder = 0.1f;

    [Export( PropertyHint.Range, "-2,2" ) ]
    public float shapeOpacityBorderOffset = 0f;

    [Export( PropertyHint.Range, "-2,2" ) ]
    public float shapeOpacityBorderSpread = 0f;

    [Export( PropertyHint.Range, "0.2,20" ) ]
    public float shapeOpacityDistribution = 1f;

     [ExportGroup( "Shape Color Mapping", "shapeColorMapping")]
    [Export( PropertyHint.Range, "-2,2" ) ]
    public float shapeColorMappingInnerBorder = -0.5f;

    [Export( PropertyHint.Range, "-2,2" ) ]
    public float shapeColorMappingOuterBorder = 0f;

    [Export( PropertyHint.Range, "-2,2" ) ]
    public float shapeColorMappingBorderOffset = 0f;

    [Export( PropertyHint.Range, "-2,2" ) ]
    public float shapeColorMappingBorderSpread = 0f;

    [Export( PropertyHint.Range, "0.2,20" ) ]
    public float shapeColorMappingDistribution = 1f;


    [ExportGroup( "Inner Color", "inner")]
    [Export( PropertyHint.Range, "-180,180" ) ]
    public float innerTemparatureOffset = 0;

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

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

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


    [ExportGroup( "Outer Color", "outer")]

    [Export( PropertyHint.Range, "-180,180" ) ]
    public float outerTemparatureOffset = 0;

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

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

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

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

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

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

      SDFTypeFlareAddShader.minShapeDistance.Set( material, shapeOpacityInnerBorder + shapeOpacityBorderOffset - shapeOpacityBorderSpread );
      SDFTypeFlareAddShader.maxShapeDistance.Set( material, shapeOpacityOuterBorder + shapeOpacityBorderOffset + shapeOpacityBorderSpread );

      SDFTypeFlareAddShader.minShapeDistanceColor.Set( material, shapeColorMappingInnerBorder + shapeColorMappingBorderOffset - shapeColorMappingBorderSpread );
      SDFTypeFlareAddShader.maxShapeDistanceColor.Set( material, shapeColorMappingOuterBorder + shapeColorMappingBorderOffset + shapeColorMappingBorderSpread );


      SDFTypeFlareAddShader.shapeColorDistortion.Set( material, shapeColorMappingDistribution );
      SDFTypeFlareAddShader.shapeAlphaDistortion.Set( material, shapeOpacityDistribution );

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

      SDFTypeFlareAddShader.shapeType.Set( material, (int) shapeType );
      SDFTypeFlareAddShader.shapeScale.Set( material, shapeScale );

      SDFTypeFlareAddShader.innerHsl.Set( material, 
        new Vector4( 
          innerTemparatureOffset / 360f ,
          innerSaturationOffset / 100f ,
          innerLightnessOffset / 100f ,
          innerOpacity 
        ) 
      );

      SDFTypeFlareAddShader.outerHsl.Set( material, 
        new Vector4( 
          outerTemparatureOffset / 360f ,
          outerSaturationOffset / 100f ,
          outerLightnessOffset / 100f ,
          outerOpacity 
        ) 
      );
    }

  }
}