package math.fractals;

import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;

public class Fractal07 extends JFrame {
    private static final long serialVersionUID = 8169105040941367402L;
    private static final int fw = 1000;
    private static final int fh = 1000;

    public static void main(String[] args) {
        //SwingUtilities.invokeLater(() -> new Fractal07(new FraktalJuliiPanel(512, -0.64f, 0.42f)));
        //SwingUtilities.invokeLater(() -> new Fractal07(new FraktalJuliiPanel(512, -0.66f, -0.424f)));
        //SwingUtilities.invokeLater(() -> new Fractal07(new FraktalJuliiPanel(512, -0.61f, -0.4f)));
        SwingUtilities.invokeLater(() -> new Fractal07(new FraktalJuliiPanel(512, -0.617f, -0.4f)));
    }

    public Fractal07(JComponent comp) {
        setLayout(null);
        setPreferredSize(new Dimension(fw, fh));
        setBounds((Toolkit.getDefaultToolkit().getScreenSize().width / 2)
                        - (fw / 2),
                (Toolkit.getDefaultToolkit().getScreenSize().height / 2)
                        - (fh / 2), fw, fh);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setTitle("Fraktal Julii");
        JPanel panel = (JPanel) comp;
        panel.setLocation((fw - panel.getWidth()) / 2,
                (fh - panel.getHeight()) / 2);
        add(panel);
        setVisible(true);
    }
}

class FraktalJuliiPanel extends JPanel {
    private static final long serialVersionUID = -5183600697149041028L;
    private static final int w = 800;
    private static final int h = 800;
    private static final double min = -2.5f;
    private static final double max = 2.5f;
    private static final double scale = (max - min) / w;
    private static final double s = 2.0;
    private final int liczbaIteracji;
    private final double re;
    private final double im;

    public FraktalJuliiPanel(int liczbaIteracji, double re, double im) {
        this.liczbaIteracji = liczbaIteracji;
        this.re = re;
        this.im = im;
        setPreferredSize(new Dimension(w, h));
        setBackground(Color.WHITE);
        setSize(w, h);
    }

    private int liczIter(double zre, double zim) {
        double kwad = 0;
        int licznik = 0;
        while ((kwad < s * s) && (licznik < liczbaIteracji)) {
            double temp = zre * zre - zim * zim + re;
            zim = s * zre * zim + im;
            zre = temp;
            kwad = zim * zim + zre * zre;
            licznik++;
        }
        return liczbaIteracji - licznik;
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        BufferedImage bimage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = bimage.createGraphics();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        g2.drawRect(0, 0, w - 1, h - 1);
        WritableRaster raster = bimage.getRaster();
        int[] rgb = new int[4];
        for (int i = 0; i < w; i++) {
            for (int j = 0; j < w; j++) {
                double zr = min + j * scale;
                double zi = min + i * scale;
                int licz = liczIter(zr, zi);
                rgb[0] = licz << 6;
                rgb[1] = licz << 5;
                rgb[2] = licz << 7;
                rgb[3] = 255;
                raster.setPixel(j, i, rgb);
            }
        }
        g.drawImage(bimage, 0, 0, this);
    }
}