// VERTEX_SHADER
uniform float u_start;
uniform float u_end;
uniform float u_color_stops[6 * 5];
uniform int u_num_color_stops;
uniform vec2 u_radius;
uniform vec2 u_center;

_OUT_ vec2 center;
_OUT_ vec4 color_stops[6];
_OUT_ float color_offsets[6];
_OUT_ float start;
_OUT_ float end;

void main() {
  gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);

  center = (u_modelview * vec4(u_center, 0, 1)).xy;
  start = u_start;
  end = u_end;

  for (int i = 0; i < u_num_color_stops; i ++) {
    color_offsets[i] = u_color_stops[(i * 5) + 0];
    color_stops[i] = gsk_premultiply(vec4(u_color_stops[(i * 5) + 1],
                                          u_color_stops[(i * 5) + 2],
                                          u_color_stops[(i * 5) + 3],
                                          u_color_stops[(i * 5) + 4]));
  }
}

// FRAGMENT_SHADER:
#ifdef GSK_LEGACY
uniform int u_num_color_stops;
#else
uniform highp int u_num_color_stops;
#endif

uniform vec2 u_radius;
uniform float u_end;

_IN_ vec2 center;
_IN_ vec4 color_stops[6];
_IN_ float color_offsets[6];
_IN_ float start;
_IN_ float end;

// The offsets in the color stops are relative to the
// start and end values of the gradient.
float abs_offset(float offset)  {
  return start + ((end - start) * offset);
}

void main() {
  vec2 pixel = gsk_get_frag_coord();
  vec2 rel = (center - pixel) / (u_radius);
  float d = sqrt(dot(rel, rel));

  if (d < abs_offset (color_offsets[0])) {
    gskSetOutputColor(color_stops[0] * u_alpha);
    return;
  }

  if (d > end) {
    gskSetOutputColor(color_stops[u_num_color_stops - 1] * u_alpha);
    return;
  }

  vec4 color = vec4(0, 0, 0, 0);
  for (int i = 1; i < u_num_color_stops; i++) {
    float last_offset = abs_offset(color_offsets[i - 1]);
    float this_offset = abs_offset(color_offsets[i]);

    // We have color_stops[i - 1] at last_offset and color_stops[i] at this_offset.
    // We now need to map `d` between those two offsets and simply mix linearly between them
    if (d >= last_offset && d <= this_offset) {
      float f = (d - last_offset) / (this_offset - last_offset);

      color = mix(color_stops[i - 1], color_stops[i], f);
      break;
    }
  }

  gskSetOutputColor(color * u_alpha);
}
