// (C) Uri Wilensky. https://github.com/NetLogo/NetLogo

package org.nlogo.render;

import org.nlogo.api.Graphics2DWrapper;
import org.nlogo.api.GraphicsInterface;

public class SpotlightDrawer
    implements Drawable {
  private java.awt.image.BufferedImage spotlightImage;


  public java.awt.image.BufferedImage getImage(TopologyRenderer topology, double xcor, double ycor,
                                               int width, int height, double patchSize,
                                               double spotlightSize, boolean dim, boolean wrap) {
    // set up the spotlight image
    if (spotlightImage == null ||
        spotlightImage.getWidth() != width ||
        spotlightImage.getHeight() != height) {
      spotlightImage = new java.awt.image.BufferedImage
          (width, height, java.awt.image.BufferedImage.TYPE_INT_ARGB);
    }

    Graphics2DWrapper sg = new Graphics2DWrapper(spotlightImage.createGraphics());
    sg.antiAliasing(true);

    if (dim) {
      sg.setComposite(java.awt.AlphaComposite.Src);
      sg.setColor(DIMMED);
      sg.fillRect(0, 0, width, height);
    } else {
      sg.setComposite(java.awt.AlphaComposite.Clear);
      sg.setColor(DIMMED);
      sg.fillRect(0, 0, width, height);
    }

    if (wrap) {
      topology.wrapDrawable(this, sg, xcor, ycor, spotlightSize, patchSize);
    } else {
      sg.push();
      double size = spotlightSize * patchSize + adjustSize(spotlightSize, patchSize);
      double offset = size / 2.0;
      double x = topology.graphicsX(xcor, patchSize) - offset;
      double y = topology.graphicsY(ycor, patchSize) - offset;
      sg.translate(x, y);
      draw(sg, size);
      sg.pop();
    }

    sg.antiAliasing(false);

    return spotlightImage;
  }

  // Don't let the spotlight be smaller than 10% of total view height / width
  public double adjustSize(double spotlightSize, double patchSize) {
    double minSize = StrictMath.max(spotlightImage.getWidth(), spotlightImage.getHeight()) / 20;
    return (spotlightSize * patchSize) < minSize ? (minSize - spotlightSize) : 0;
  }

  static java.awt.Color DIMMED =
      new java.awt.Color(0, 0, 50, 100);
  private static final java.awt.Color SPOTLIGHT_INNER_BORDER =
      new java.awt.Color(200, 255, 255, 100);
  private static final java.awt.Color SPOTLIGHT_OUTER_BORDER =
      new java.awt.Color(200, 255, 255, 50);

  private static final double OUTER = 10;
  private static final double MIDDLE = 8;
  private static final double INNER = 4;

  private static final java.awt.geom.Ellipse2D.Double ellipse = new java.awt.geom.Ellipse2D.Double(0, 0, 1, 1);

  public void draw(GraphicsInterface g, double size) {
    // Clear out area for spotlight
    g.setComposite(java.awt.AlphaComposite.Clear);
    drawEllipse(g, MIDDLE + size, -MIDDLE / 2);

    // halo is composed of three overlapping circles
    g.setComposite(java.awt.AlphaComposite.Src);

    g.setColor(DIMMED);
    drawEllipse(g, OUTER + size, -OUTER / 2);

    g.setColor(SPOTLIGHT_OUTER_BORDER);
    drawEllipse(g, MIDDLE + size, -MIDDLE / 2);

    g.setColor(SPOTLIGHT_INNER_BORDER);
    drawEllipse(g, INNER + size, -INNER / 2);

    // this middle of the spotlight is clear
    g.setComposite(java.awt.AlphaComposite.Clear);
    drawEllipse(g, size, 0);
  }

  private void drawEllipse(GraphicsInterface g, double size, double offset) {
    g.push();
    g.translate(offset, offset);
    g.scale(size, size);
    g.fill(ellipse);
    g.pop();
  }
}
