package math.autos;

import math.utils.ArrayUtil;

import javax.swing.*;
import java.awt.*;
import java.util.Timer;
import java.util.TimerTask;

public class AntLangton extends JPanel {
    private static final long serialVersionUID = -5529472311997280826L;
    private static final int w = 800;
    private static final int h = 800;
    private static final int liczbaPol = 100;
    private static final int ap = liczbaPol / 2;
    private static final int szer = 8;
    private static final int len = szer * liczbaPol;
    private static final Color CW = Color.WHITE;
    private static final Color CB = Color.BLACK;
    private static final Color CR = Color.RED;
    private int[][] autos1;//komorki aktualne
    private int[][] autos2;//komorki nastepnej generacji
    private final int milis;
    private int antx;
    private int anty;
    private int antDir;

    public AntLangton(int milis) {
        this.milis = milis;
        setPreferredSize(new Dimension(w, h));
        setSize(w, h);
        setBackground(Color.WHITE);
        autos1 = new int[liczbaPol][liczbaPol];
        autos2 = new int[liczbaPol][liczbaPol];
        clear();
        antx = ap;//25
        anty = ap;//25
        antDir = 1;
        Timer timer = new Timer();
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                autos2 = ArrayUtil.clone(autos1);
                antDir = changeDir(antDir, autos2[antx][anty]);
                if (autos2[antx][anty] == 0) {
                    autos2[antx][anty]++;
                } else if (autos2[antx][anty] == 1) {
                    autos2[antx][anty]--;
                }
                if (antDir == 1) {
                    anty--;
                    if (anty == -1) {
                        anty = liczbaPol - 1;
                    }
                } else if (antDir == 2) {
                    antx--;
                    if (antx == -1) {
                        antx = liczbaPol - 1;
                    }
                } else if (antDir == 3) {
                    anty++;
                    if (anty == liczbaPol) {
                        anty = 0;
                    }
                } else if (antDir == 4) {
                    antx++;
                    if (antx == liczbaPol) {
                        antx = 0;
                    }
                }
                autos1 = ArrayUtil.clone(autos2);
                repaint();
            }
        };
        timer.schedule(timerTask, 100, milis);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setColor(CW);
        g2.fillRect(0, 0, w, h);
        g2.setColor(Color.LIGHT_GRAY);
        int z = 0;//polozenie linii
        for (int i = 0; i <= liczbaPol + 1; i++) {
            g2.drawLine(0, z, len, z);
            g2.drawLine(z, 0, z, len);
            z += szer;
        }
        g2.setColor(CB);
        for (int i = 0; i < liczbaPol; i++) {
            for (int j = 0; j < liczbaPol; j++) {
                int x = i * szer;
                int y = j * szer;
                if (autos1[i][j] == 1) {
                    g2.fillRect(x, y, szer, szer);
                }
                g2.setColor(CR);
                g2.fillOval(antx * szer, anty * szer, szer, szer);
                g2.setColor(CB);
            }
        }
    }

    public void clear() {
        for (int j = 0; j < liczbaPol; j++) {
            for (int k = 0; k < liczbaPol; k++) {
                this.autos1[j][k] = 0;
                this.autos2[j][k] = 0;
            }
        }
    }

    public static int changeDir(int dir, int col) {
        int newDir = 0;
        switch (dir) {
            case 1:
                if (col == 0) {
                    newDir = 2;
                } else if (col == 1) {
                    newDir = 4;
                }
                break;
            case 2:
                if (col == 0) {
                    newDir = 3;
                } else if (col == 1) {
                    newDir = 1;
                }
                break;
            case 3:
                if (col == 0) {
                    newDir = 4;
                } else if (col == 1) {
                    newDir = 2;
                }
                break;
            case 4:
                if (col == 0) {
                    newDir = 1;
                } else if (col == 1) {
                    newDir = 3;
                }
                break;
        }
        return newDir;
    }

    public void putStructure(int x, int y, int[][] array) {
        clear();
        for (int i = 0; i < array.length; i++) {
            System.arraycopy(array[i], 0, this.autos1[i + y], 0 + x, array[0].length);
        }
    }

    public int getMilis() {
        return milis;
    }
}
