package math.fractals;

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

public class Fractal09 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 Fractal09(new BurningShipPanel(75, -0.3, -0.3)));
    }

    public Fractal09(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 BurningShipPanel 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.4f;
    private static final double max = 2.4f;
    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 BurningShipPanel(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 zr = 0;
        double zi = 0;
        double kwad = 0;
        int licznik = 0;
        while ((kwad < s * s) && (licznik < liczbaIteracji)) {
            double tempr = zr * zr - zi * zi + zre;
            double tempi = 2 * Math.abs(zr * zi) + zim;
            zr = tempr;
            zi = tempi;
            kwad = zi * zi + zr * zr;
            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 >> 3) & 0x07) << 5;
                rgb[1] = ((licz >> 3) & 0x07) << 5;
                rgb[2] = ((licz >> 5) & 0x07) << 5;
                rgb[3] = 255;
                raster.setPixel(j, i, rgb);
            }
        }
        g.drawImage(bimage, 0, 0, this);
    }

    public double getRe() {
        return re;
    }

    public double getIm() {
        return im;
    }
}