package approach3.parallel.operations;

import approach3.parallel.SharedRessources;

// Source: https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm#All_cases
public class Trace implements Runnable {

    private int x0, y0;
    private int x1, y1;

    private int step;

    public Trace(int x0, int y0, int x1, int y1, int step) {
        this.x0 = x0;
        this.y0 = y0;

        this.x1 = x1;
        this.y1 = y1;

        this.step = step;
    }

    @Override
    public void run() {

        int oldX = 0;
        int oldY = 0;


        int dx = Math.abs(x1 - x0);
        int sx = x0 < x1 ? 1 : -1;

        int dy = -Math.abs(y1 - y0);
        int sy = y0 < y1 ? 1 : -1;

        int err = dx + dy;

        while (true) {

            if (SharedRessources.getInstance().isFound())
                return;


            oldX = x0;
            oldY = y0;

            if (x0 == x1 && y0 == y1) {
                SharedRessources.getInstance().setFound(true);
                System.out.println("Start-End-Connection established");
                break;
            }

            int err2 = 2 * err;

            if (err2 >= dy) {
                err += dy;
                x0 += sx;
            }
            if (err2 <= dx) {
                err += dx;
                y0 += sy;
            }

            int currentStep
                    = SharedRessources.getInstance().getStep(x0, y0);

            if (step < currentStep) {
                int dirX = x0 - oldX;
                int dirY = y0 - oldY;

                SharedRessources.getInstance()
                        .setData(x0, y0, -dirX, -dirY, step);

            }

            if (SharedRessources.getInstance().isWall(x0, y0)) {

                if (step < SharedRessources.getInstance().getStep(oldX - 1, oldY)) {
                    SharedRessources
                            .getInstance()
                            .getExecutor()
                            .execute(new Flood(oldX - 1, oldY, step));

                    SharedRessources.getInstance()
                            .setData(oldX - 1, oldY, 1, 0, step);
                }


                if (step < SharedRessources.getInstance().getStep(oldX + 1, oldY)) {
                    SharedRessources
                            .getInstance()
                            .getExecutor()
                            .execute(new Flood(oldX + 1, oldY, step));

                    SharedRessources.getInstance()
                            .setData(oldX + 1, oldY, -1, 0, step);
                }

                if (step < SharedRessources.getInstance().getStep(oldX, oldY - 1)) {
                    SharedRessources
                            .getInstance()
                            .getExecutor()
                            .execute(new Flood(oldX, oldY - 1, step));

                    SharedRessources.getInstance()
                            .setData(oldX, oldY - 1, 0, 1, step);

                }

                if (step < SharedRessources.getInstance().getStep(oldX, oldY + 1)) {
                    SharedRessources
                            .getInstance()
                            .getExecutor()
                            .execute(new Flood(oldX, oldY + 1, step));

                    SharedRessources.getInstance()
                            .setData(oldX, oldY + 1, 0, -1, step);

                }

                break;
            }


            step++;

        }

    }
}