import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;

public class AuroraLife extends JPanel implements ActionListener, MouseListener {
    private final int cellSize = 8;
    private final int rows = 100, cols = 100;
    private final float[][] energy = new float[rows][cols];
    private final boolean[][] grid = new boolean[rows][cols];
    private final Timer timer;

    public AuroraLife() {
        setPreferredSize(new Dimension(cols * cellSize, rows * cellSize));
        setBackground(Color.BLACK);
        addMouseListener(this);
        randomizeGrid();
        timer = new Timer(80, this);
        timer.start();
    }

    private void randomizeGrid() {
        Random rand = new Random();
        for (int r = 0; r < rows; r++)
            for (int c = 0; c < cols; c++)
                grid[r][c] = rand.nextDouble() < 0.2; // 20% chance alive
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        updateLife();
        repaint();
    }

    private void updateLife() {
        boolean[][] newGrid = new boolean[rows][cols];
        for (int r = 0; r < rows; r++) {
            for (int c = 0; c < cols; c++) {
                int neighbors = countNeighbors(r, c);
                if (grid[r][c]) {
                    newGrid[r][c] = (neighbors == 2 || neighbors == 3);
                } else {
                    newGrid[r][c] = (neighbors == 3);
                }

                // energy updates
                if (newGrid[r][c]) {
                    energy[r][c] = Math.min(1f, energy[r][c] + 0.2f);
                } else {
                    energy[r][c] = Math.max(0f, energy[r][c] - 0.05f);
                }
            }
        }
        for (int r = 0; r < rows; r++)
            System.arraycopy(newGrid[r], 0, grid[r], 0, cols);
    }

    private int countNeighbors(int r, int c) {
        int count = 0;
        for (int dr = -1; dr <= 1; dr++)
            for (int dc = -1; dc <= 1; dc++) {
                if (dr == 0 && dc == 0) continue;
                int nr = (r + dr + rows) % rows;
                int nc = (c + dc + cols) % cols;
                if (grid[nr][nc]) count++;
            }
        return count;
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        for (int r = 0; r < rows; r++) {
            for (int c = 0; c < cols; c++) {
                float e = energy[r][c];
                if (e > 0.01f) {
                    Color col = Color.getHSBColor(0.6f - 0.4f * e, 1f, e);
                    g2.setColor(col);
                    g2.fillRect(c * cellSize, r * cellSize, cellSize, cellSize);
                }
            }
        }
    }

    // click to toggle cells
    @Override public void mouseClicked(MouseEvent e) {
        int c = e.getX() / cellSize;
        int r = e.getY() / cellSize;
        if (r >= 0 && r < rows && c >= 0 && c < cols) {
            grid[r][c] = !grid[r][c];
            energy[r][c] = grid[r][c] ? 1f : 0f;
        }
    }
    @Override public void mousePressed(MouseEvent e) {}
    @Override public void mouseReleased(MouseEvent e) {}
    @Override public void mouseEntered(MouseEvent e) {}
    @Override public void mouseExited(MouseEvent e) {}

    public static void main(String[] args) {
        JFrame frame = new JFrame("Aurora Life — Creative Cellular Simulation");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);
        frame.add(new AuroraLife());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}
