package graphics.sprials;

import java.awt.*;

public class Spirals {
  private int cx = 0; // always translated
  private int cy = 0;

  public void move(double x, double y) {
    move((int) x, (int) y);
  }

  public void move(int x, int y) {
    cx = x + tx;
    cy = y + ty;
  }

  private int tx = 60;
  private int ty = 60;

  public void setSize(java.awt.Dimension d) {
    tx = d.width / 2;
    ty = d.height / 2;
  }

  public void drawp(int r, double a, java.awt.Graphics g) {
    a = a * Math.PI / 180;
    draw((int) (r * Math.cos(a)), (int) (r * Math.sin(a)), g);
  }

  public void draw(int x, int y, java.awt.Graphics g) {
    g.drawLine(cx, cy, x + tx, (y + ty));
    move(x, y);
  }

  public void drawTree(Graphics g) {
    move(25, 25);
    drawTree(2, 2.3, 4, -90, 6, 5, 5, g);
  }

  public void drawTree(double fanRatio, double lengthRatio, int numBranch,
                       double a, double l, double f, int n, Graphics g) {
    int num;
    double delang, ang;
    if (n <= 0) {
      drawLeaf(g);
      return;
    }
    drawp(l, a, g);
    num = numBranch;
    if (num > 1)
      delang = f / (num - 1.0);
    else
      delang = 0;
    ang = a - f / 2.0 - delang;
    for (int i = 0; i < num; i++) {
      ang = ang + delang;
      drawTree(fanRatio,
               lengthRatio,
               numBranch,
               ang - (ang * 0.1 * Math.random()),
               l * lengthRatio,
               f * fanRatio,
               n - 1, g);
    }
  }

  private java.awt.Image img = graphics.ImageUtils.open();

  public void rdrawImage(double x, double y, java.awt.Graphics g) {
    g.drawImage(img, (int) x, (int) y, 20, 20, null);
  }

  public void draw(double x, double y, java.awt.Graphics g) {
    draw((int) x, (int) y, g);
  }

  public void drawp(double x, double y, java.awt.Graphics g) {
    drawp((int) x, (int) y, g);
  }

  public void movep(int r, double a) {
    a = a * Math.PI / 180;
    move((int) (r * Math.cos(a)), (int) (r * Math.sin(a)));
  }

  public void movep(double x, double y) {
    movep((int) x, (int) y);
  }


  public void drawCircle(java.awt.Graphics g) {
    for (int a = 0; a <= 360; a = a + 360 / 8) {
      if (a == 0) movep(50, a);
      drawp(50, a, g);
    }
  }

  public static javax.swing.JComponent getArchimedesSpiral() {
    return new javax.swing.JComponent() {
      Spirals s = new Spirals();

      public void paint(Graphics g) {
        s.setSize(getSize());
        s.archimedesSpiral(0.1, g);
      }

      public Dimension getPreferredSize() {
        return new Dimension(200, 200);
      }
    };

  }

  public double archimedes(double k, double theta) {
    return k * theta;
  }

  public void archimedesSpiral(double k, java.awt.Graphics g) {
    double theta = 0;
    double r = archimedes(k, theta);
    movep(r, theta);
    for (int s = 1; s < 12000; s++, theta += 3) {
      r = archimedes(k, theta);
      drawp(r, theta, g);
    }
  }

  public void archimedesImage(double k, java.awt.Graphics g) {
    double theta = 0;
    double r = archimedes(k, theta);
    movep(r, theta);
    for (int s = 1; s < 12000; s++, theta += 3) {
      r = archimedes(k, theta);
      drawImage(r, theta, g);
    }
  }

  public void equiangularSpiral(java.awt.Graphics g) {
    double a = 0;
    double k = 1.5;
    for (int s = 1; s < 1600; s++, a += 3) {
      double r = Math.pow(k, a);
      if (s == 1) movep(r, a);
      drawp(r, a, g);
    }
  }

  public void fermatsSpiral(
      double k,
      double c,
      java.awt.Graphics g) {
    double d = 360 / c;
    double a = 0;
    for (int s = -600; s < 600; s++, a += d) {
      double r = Math.sqrt(a) * k;
      movep(r, a);
      //drawHex(r,a,g);
      drawImage(r, a, g);
    }
  }

  public void tile31_1(int modf,
                       double alpha, double gamma,
                       java.awt.Dimension d, java.awt.Graphics g) {
    double beta1 = -11;
    double beta2 = -12;
    for (int i = 0; i < d.width; i++)
      for (int j = 0; j < d.height; j++) {
        double x = beta1 + gamma * i;
        double y = beta2 + gamma * j;
        double z = alpha * (Math.sin(x) + Math.sin(y));
        int c = (int) z;
        if ((c % modf) == 0) {
          g.setColor(new java.awt.Color(c));
          move(i, j);
          draw(i, j, g);
        }
      }
  }

  public void drawHex(double r, double a, java.awt.Graphics g) {
    for (int t = 0; t <= 6; t++) {
      double aa = 360 * t / 6 + a;
      double rr = 3;
      double x = rr * cos(aa) + r * cos(a);
      double y = rr * sin(aa) + r * sin(a);
      if (t == 0) move(x, y);
      draw(x, y, g);
    }
  }

  public void drawLeaf(Graphics g) {
    //g.drawString("*",cx,cy);
    g.drawImage(img, cx, cy, 30, 30, null);
  }

  public void drawImage(double r, double a, java.awt.Graphics g) {
    double rr = 3;
    a = -a * Math.PI / 180;
    int x = (int) Math.round(r * Math.cos(a));
    int y = (int) Math.round(r * Math.sin(a));
    g.drawString("*", cx, cy);

    //g.drawImage(img,(int)x,(int)y,10,10,null);
  }

  public static double cos(double a) {
    return Math.cos(a * Math.PI / 180);
  }

  public static double sin(double a) {
    return Math.sin(a * Math.PI / 180);
  }

  public void starPolygon(int n, int m, java.awt.Graphics g) {
    for (int s = 0; s <= n; s++) {
      double a = 360 * s * m / n;
      if (s == 0) movep(5, a);
      drawp(5, a, g);
    }
  }

  public static void main(String args[]) {
    gui.ClosableJFrame cf = new gui.ClosableJFrame();
    java.awt.Container c = cf.getContentPane();
    c.setLayout(new java.awt.FlowLayout());
    c.add(getArchimedesSpiral());
    c.add(getArchimedesSpiral());
    cf.setSize(200, 200);
    cf.setVisible(true);
  }

  private void setCx(int cx) {
    this.cx = cx;
  }

  private void setCy(int cy) {
    this.cy = cy;
  }

  private void setTx(int tx) {
    this.tx = tx;
  }

  private void setTy(int ty) {
    this.ty = ty;
  }

  private void setImg(java.awt.Image img) {
    this.img = img;
  }

}