#define MAX_COLORS 10

#define CLAMP_STEP 0
#define SMOOTH_STEP 1

float radius(float x, float y, vec2 center, float radiusX, float radiusY) {
  float rad = atan(y - center.y, x - center.x);

  return (radiusX * radiusY) /
    sqrt(radiusX * radiusX * sin(rad) * sin(rad) + radiusY * radiusY * cos(rad) * cos(rad));
}

vec4 ellipticalGradient(
  int amount,
  vec4 colors[MAX_COLORS],
  float stops[MAX_COLORS],
  vec2 center,
  float radiusX,
  float radiusY,
  float mixStep
) {
  vec2 uv = destCoord();

  float d = distance(center, uv) / radius(uv.x, uv.y, center, radiusX, radiusY);

  vec4 color = colors[0];
  for (int i = 1; i < amount; i++) {
    color = mix(
      color,
      colors[i],
      int(mixStep) == CLAMP_STEP
        ? clamp((d - stops[i - 1]) / (stops[i] - stops[i - 1]), 0.0, 1.0)
        : smoothstep(stops[i - 1], stops[i], d)
    );
  }
  return color;
}

kernel vec4 ellipticalGradient1Kernel(
  __color color0,
  float stop0,
  vec2 center,
  float radiusX,
  float radiusY,
  float mixStep
) {
  vec4 colors[MAX_COLORS];
  colors[0] = color0;

  float stops[MAX_COLORS];
  stops[0] = stop0;

  return ellipticalGradient(1, colors, stops, center, radiusX, radiusY, mixStep);
}

kernel vec4 ellipticalGradient2Kernel(
  __color color0,
  float stop0,
  __color color1,
  float stop1,
  vec2 center,
  float radiusX,
  float radiusY,
  float mixStep
) {
  vec4 colors[MAX_COLORS];
  colors[0] = color0;
  colors[1] = color1;

  float stops[MAX_COLORS];
  stops[0] = stop0;
  stops[1] = stop1;

  return ellipticalGradient(2, colors, stops, center, radiusX, radiusY, mixStep);
}

kernel vec4 ellipticalGradient3Kernel(
  __color color0,
  float stop0,
  __color color1,
  float stop1,
  __color color2,
  float stop2,
  vec2 center,
  float radiusX,
  float radiusY,
  float mixStep
) {
  vec4 colors[MAX_COLORS];
  colors[0] = color0;
  colors[1] = color1;
  colors[2] = color2;

  float stops[MAX_COLORS];
  stops[0] = stop0;
  stops[1] = stop1;
  stops[2] = stop2;

  return ellipticalGradient(3, colors, stops, center, radiusX, radiusY, mixStep);
}

kernel vec4 ellipticalGradient4Kernel(
  __color color0,
  float stop0,
  __color color1,
  float stop1,
  __color color2,
  float stop2,
  __color color3,
  float stop3,
  vec2 center,
  float radiusX,
  float radiusY,
  float mixStep
) {
  vec4 colors[MAX_COLORS];
  colors[0] = color0;
  colors[1] = color1;
  colors[2] = color2;
  colors[3] = color3;

  float stops[MAX_COLORS];
  stops[0] = stop0;
  stops[1] = stop1;
  stops[2] = stop2;
  stops[3] = stop3;

  return ellipticalGradient(4, colors, stops, center, radiusX, radiusY, mixStep);
}

kernel vec4 ellipticalGradient5Kernel(
  __color color0,
  float stop0,
  __color color1,
  float stop1,
  __color color2,
  float stop2,
  __color color3,
  float stop3,
  __color color4,
  float stop4,
  vec2 center,
  float radiusX,
  float radiusY,
  float mixStep
) {
  vec4 colors[MAX_COLORS];
  colors[0] = color0;
  colors[1] = color1;
  colors[2] = color2;
  colors[3] = color3;
  colors[4] = color4;

  float stops[MAX_COLORS];
  stops[0] = stop0;
  stops[1] = stop1;
  stops[2] = stop2;
  stops[3] = stop3;
  stops[4] = stop4;

  return ellipticalGradient(5, colors, stops, center, radiusX, radiusY, mixStep);
}

kernel vec4 ellipticalGradient6Kernel(
  __color color0,
  float stop0,
  __color color1,
  float stop1,
  __color color2,
  float stop2,
  __color color3,
  float stop3,
  __color color4,
  float stop4,
  __color color5,
  float stop5,
  vec2 center,
  float radiusX,
  float radiusY,
  float mixStep
) {
  vec4 colors[MAX_COLORS];
  colors[0] = color0;
  colors[1] = color1;
  colors[2] = color2;
  colors[3] = color3;
  colors[4] = color4;
  colors[5] = color5;

  float stops[MAX_COLORS];
  stops[0] = stop0;
  stops[1] = stop1;
  stops[2] = stop2;
  stops[3] = stop3;
  stops[4] = stop4;
  stops[5] = stop5;

  return ellipticalGradient(6, colors, stops, center, radiusX, radiusY, mixStep);
}

kernel vec4 ellipticalGradient7Kernel(
  __color color0,
  float stop0,
  __color color1,
  float stop1,
  __color color2,
  float stop2,
  __color color3,
  float stop3,
  __color color4,
  float stop4,
  __color color5,
  float stop5,
  __color color6,
  float stop6,
  vec2 center,
  float radiusX,
  float radiusY,
  float mixStep
) {
  vec4 colors[MAX_COLORS];
  colors[0] = color0;
  colors[1] = color1;
  colors[2] = color2;
  colors[3] = color3;
  colors[4] = color4;
  colors[5] = color5;
  colors[6] = color6;

  float stops[MAX_COLORS];
  stops[0] = stop0;
  stops[1] = stop1;
  stops[2] = stop2;
  stops[3] = stop3;
  stops[4] = stop4;
  stops[5] = stop5;
  stops[6] = stop6;

  return ellipticalGradient(7, colors, stops, center, radiusX, radiusY, mixStep);
}

kernel vec4 ellipticalGradient8Kernel(
  __color color0,
  float stop0,
  __color color1,
  float stop1,
  __color color2,
  float stop2,
  __color color3,
  float stop3,
  __color color4,
  float stop4,
  __color color5,
  float stop5,
  __color color6,
  float stop6,
  __color color7,
  float stop7,
  vec2 center,
  float radiusX,
  float radiusY,
  float mixStep
) {
  vec4 colors[MAX_COLORS];
  colors[0] = color0;
  colors[1] = color1;
  colors[2] = color2;
  colors[3] = color3;
  colors[4] = color4;
  colors[5] = color5;
  colors[6] = color6;
  colors[7] = color7;

  float stops[MAX_COLORS];
  stops[0] = stop0;
  stops[1] = stop1;
  stops[2] = stop2;
  stops[3] = stop3;
  stops[4] = stop4;
  stops[5] = stop5;
  stops[6] = stop6;
  stops[7] = stop7;

  return ellipticalGradient(8, colors, stops, center, radiusX, radiusY, mixStep);
}

kernel vec4 ellipticalGradient9Kernel(
  __color color0,
  float stop0,
  __color color1,
  float stop1,
  __color color2,
  float stop2,
  __color color3,
  float stop3,
  __color color4,
  float stop4,
  __color color5,
  float stop5,
  __color color6,
  float stop6,
  __color color7,
  float stop7,
  __color color8,
  float stop8,
  vec2 center,
  float radiusX,
  float radiusY,
  float mixStep
) {
  vec4 colors[MAX_COLORS];
  colors[0] = color0;
  colors[1] = color1;
  colors[2] = color2;
  colors[3] = color3;
  colors[4] = color4;
  colors[5] = color5;
  colors[6] = color6;
  colors[7] = color7;
  colors[8] = color8;

  float stops[MAX_COLORS];
  stops[0] = stop0;
  stops[1] = stop1;
  stops[2] = stop2;
  stops[3] = stop3;
  stops[4] = stop4;
  stops[5] = stop5;
  stops[6] = stop6;
  stops[7] = stop7;
  stops[8] = stop8;

  return ellipticalGradient(9, colors, stops, center, radiusX, radiusY, mixStep);
}

kernel vec4 ellipticalGradient10Kernel(
  __color color0,
  float stop0,
  __color color1,
  float stop1,
  __color color2,
  float stop2,
  __color color3,
  float stop3,
  __color color4,
  float stop4,
  __color color5,
  float stop5,
  __color color6,
  float stop6,
  __color color7,
  float stop7,
  __color color8,
  float stop8,
  __color color9,
  float stop9,
  vec2 center,
  float radiusX,
  float radiusY,
  float mixStep
) {
  vec4 colors[MAX_COLORS];
  colors[0] = color0;
  colors[1] = color1;
  colors[2] = color2;
  colors[3] = color3;
  colors[4] = color4;
  colors[5] = color5;
  colors[6] = color6;
  colors[7] = color7;
  colors[8] = color8;
  colors[9] = color9;

  float stops[MAX_COLORS];
  stops[0] = stop0;
  stops[1] = stop1;
  stops[2] = stop2;
  stops[3] = stop3;
  stops[4] = stop4;
  stops[5] = stop5;
  stops[6] = stop6;
  stops[7] = stop7;
  stops[8] = stop8;
  stops[9] = stop9;

  return ellipticalGradient(10, colors, stops, center, radiusX, radiusY, mixStep);
}
