package math.autos;

import math.color.ColorUtil;
import math.utils.ArrayUtil;
import math.utils.MathUtil;

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

public class NSCar 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 szer = 8;
    private static final int len = szer * liczbaPol;
    private static final int params = 2;//predkosc, kolor
    private int[][] autos1;//komorki aktualne
    private int[][] autos2;//komorki nastepnej generacji
    private final int milis;

    public NSCar(int milis) {
        this.milis = milis;
        setPreferredSize(new Dimension(w, h));
        setSize(w, h);
        setBackground(Color.WHITE);
        autos1 = new int[liczbaPol][params];
        autos2 = new int[liczbaPol][params];
        clear();
        Timer timer = new Timer();
        //przegladamy wszystkie komorki zaczynajac od ostatniej
        //sprawdzamy czy komorka jest zajeta czy nie
        //jesli tak zapisujemy predkosc
        //sprawdzamy liczbe pustych kratek przed samochodem
        //czyli odleglosc od poprzedzającego samochodu
        //jesli kratka jest wolna
        //zwiekszamy dystans
        //jesli jest zajeta - przerywamy zliczanie
        //dystansu
        //jesli samochod ma zbyt duza szybkosc w stosunku
        //do odleglosci - zmniejszamy szybkosc
        //albo jesli samochod ma wolna odleglosc, a nie
        //ma maksynmalnej szybkosc - podnosimy szybkosc 0 1
        //wprowadzamy czynnik rozpraszający kierowcę
        //co powoduje hamowanie
        //jesli szybkosc jest wieksza od zero
        //przestawiamy samochod do przodu
        //indeks komórki tablicy zawierającej ostatni samochód;
        //jeśli w tablicy nie ma zadnego samochodu indeks bedzie
        //mial wartosc 100;
        //jesli w pierwszej komorce od lewej nie ma samochodu
        //
        //int s = Math.min(index, 5);
        //System.out.println(index + " " + s + " " + c);
        //-
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                autos2 = ArrayUtil.clone(autos1);
                //przegladamy wszystkie komorki zaczynajac od ostatniej
                for (int i = liczbaPol - 1; i >= 0; i--) {
                    int speed = 0;
                    int dist = 0;
                    //sprawdzamy czy komorka jest zajeta czy nie
                    if (autos2[i][0] != -1) {
                        //jesli tak zapisujemy predkosc
                        speed = autos2[i][0];
                        //sprawdzamy liczbe pustych kratek przed samochodem
                        //czyli odleglosc od poprzedzającego samochodu
                        for (int j = i + 1; j < liczbaPol; j++) {
                            //jesli kratka jest wolna
                            if (autos2[j][0] == -1) {
                                //zwiekszamy dystans
                                dist++;
                            }
                            //jesli jest zajeta - przerywamy zliczanie
                            //dystansu
                            else {
                                break;
                            }
                        }
                        //jesli samochod ma zbyt duza szybkosc w stosunku
                        //do odleglosci - zmniejszamy szybkosc
                        if (dist < speed) {
                            speed = dist;
                        }
                        //albo jesli samochod ma wolna odleglosc, a nie
                        //ma maksynmalnej szybkosc - podnosimy szybkosc 0 1
                        else if ((dist > speed) && (speed < 5)) {
                            speed++;
                        }
                        //wprowadzamy czynnik rozpraszający kierowcę
                        //co powoduje hamowanie
                        Random rand = new Random();
                        float rand1 = rand.nextFloat();
                        if (rand1 < 0.3) {
                            if (speed > 0) {
                                speed--;
                            }
                        }
                        //jesli szybkosc jest wieksza od zero
                        //przestawiamy samochod do przodu
                        if ((speed > 0) && (i + speed < 99)) {
                            autos2[i + speed][0] = speed;
                            autos2[i + speed][1] = autos2[i][1];
                            autos2[i][0] = -1;
                            autos2[i][1] = -1;
                        } else {
                            autos2[i][0] = -1;
                            autos2[i][1] = -1;
                        }
                    }
                }
                //indeks komórki tablicy zawierającej ostatni samochód;
                //jeśli w tablicy nie ma zadnego samochodu indeks bedzie
                //mial wartosc 100;
                int index = 100;
                for (int m = 0; m < liczbaPol; m++) {
                    if (autos2[m][0] != -1) {
                        index = m;
                        break;
                    }
                }
                //jesli w pierwszej komorce od lewej nie ma samochodu
                Random random = new Random();
                if (index > 0) {
                    double x = random.nextDouble();
                    if (x < 0.7) {
                        //
                        //int s = Math.min(index, 5);
                        int s = 1;
                        int c = MathUtil.randomInRange(0, 9);
                        autos2[0][0] = s;
                        autos2[0][1] = c;
                        //System.out.println(index + " " + s + " " + c);
                    }
                }
                //-
                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(Color.WHITE);
        g2.fillRect(0, 0, w, h);
        g2.setColor(Color.LIGHT_GRAY);
        int z = 0;
        g2.drawLine(0, len / 2, len, len / 2);
        g2.drawLine(0, szer + len / 2, len, szer + len / 2);
        for (int i = 0; i <= liczbaPol + 1; i++) {
            g2.drawLine(z, len / 2, z, szer + len / 2);
            z += szer;
        }
        for (int i = 0; i < liczbaPol; i++) {
            if (autos1[i][1] > -1) {
                g2.setColor(ColorUtil.kolorySamochodow[autos1[i][1]]);
                g2.fillRect(1 + i * szer, 2 + len / 2, szer - 2, szer / 2);
            }
        }
        g2.setColor(Color.BLACK);
        for (int i = 0; i < liczbaPol; i++) {
            if (autos1[i][0] > -1) {
                g2.drawString("" + autos1[i][0], 1 + i * szer, -5 + len / 2);
            }
        }
    }

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

    public int getMilis() {
        return milis;
    }
}
