
#include <metal_stdlib>
using namespace metal;

constant float PI = 3.14159265358979323846;

struct Uniforms_MaskingRepeatCircle {
    float radius;
    float space_scale;
    float space_rotation;
    
    float pattern_one_and_one_mix;
    float x_offset;
    float y_offset;
    float invert_mix;
};

float masking_repeat_circle_mod(float a, float b) {
    return a - b * floor(a / b);
}

float2 masking_repeat_circle_mod_v2(float2 a, float b) {
    float x = masking_repeat_circle_mod(a.x, b);
    float y = masking_repeat_circle_mod(a.y, b);
    return float2(x, y);
}

struct VertexOut_MaskingRepeatCircle {
    float4 position [[ position ]];
    float2 uv;
};

float masking_repeat_circle_sdf(float2 p, float r) {
    return length(p) - r;
}

float masking_repeat_circle_two_pi_ratio(float ratio) {
    return (2.0 * PI) * ratio;
}

float2 masking_repeat_circle_rotate_point(float2 point, float angle) {
    float cosTheta = cos(angle);
    float sinTheta = sin(angle);
    float2x2 rotationMatrix = float2x2(
        cosTheta, -sinTheta,
        sinTheta,  cosTheta
    );
    return rotationMatrix * point;
}

fragment float4 masking_repeat_circle_frag(
VertexOut_MaskingRepeatCircle in [[ stage_in ]],
constant Uniforms_MaskingRepeatCircle &u [[ buffer(0) ]],
float4 color [[ color(0) ]]) {

//    const float space_scale         = 1.0;
//    const float space_rotation      = 0.125;
//    
//    const float p_one_and_one_mix   = 1.0;
//    const float x_offset            = 0.71;
//    const float y_offset            = 0.0;
//    const float radius              = 0.5;
//    const float invert_mix          = u.invert_mix;
    
    float space_scale = u.space_scale;
    float space_rotation = u.space_rotation;
    
    float pattern_one_and_one_mix = u.pattern_one_and_one_mix;
    float x_offset = u.x_offset;
    float y_offset = u.y_offset;
    float radius = u.radius;
    float invert_mix = u.invert_mix;
    
    float2 uv = in.uv;
    uv.x += x_offset;
    uv.y += y_offset;
    
    uv -= 0.5;
    uv = masking_repeat_circle_rotate_point(uv, PI * 2.0 * space_rotation);
    uv *= space_scale;
    uv += 0.5;
    
    float2 adjustedUVs = uv;
    float2 evenOdd = floor(masking_repeat_circle_mod_v2(adjustedUVs, 2.0));
    
    // View even or odd pattern with this
    // return float4(evenOdd.x, evenOdd.y, 0.0, 1.0);
    
    adjustedUVs = masking_repeat_circle_mod_v2(adjustedUVs, 1.0);
    adjustedUVs -= 0.5;
    
    float is_one_and_one_match = min(evenOdd.x, evenOdd.y);
    float mix_color = mix(1.0, min(is_one_and_one_match, pattern_one_and_one_mix), is_one_and_one_match);
    
    float dist = masking_repeat_circle_sdf(adjustedUVs, radius);
    float blurring = 0.00001;
    dist = smoothstep(0.0, blurring, dist);

    float color_value = 1.0 - dist;
    color_value = color_value * mix_color;
    float invert_color_value = 1.0 - color_value;
    
    float final_color = mix(color_value, invert_color_value, invert_mix);
    return float4(final_color, final_color, final_color, 1.0);
}
