package parallel;

import algorithm.Explorer;
import algorithm.WorkingExplorers;
import structs.Vec3;

import java.util.Stack;

public class SharedRessources {
    private static int USING_CORES;

    /***
     * Use Integer.MAX_VALUE for all cores
     * @param cores
     */
    public static void setMaximumCores(int cores) {
        if (cores >= Runtime.getRuntime().availableProcessors())
            cores = Runtime.getRuntime().availableProcessors();
        USING_CORES = cores;
    }

    private static SharedRessources sharedRessources;

    public static SharedRessources getInstance() {
        if (sharedRessources == null)
            sharedRessources = new SharedRessources(USING_CORES);
        return sharedRessources;
    }

    private SharedRessources(int cores) {
        maxCores = cores;
        System.out.println("[*] Using " + maxCores + " cores.");

        signalingObject = new Object();

        workingThreads = new WorkingExplorers[maxCores];
        for (int i = 0; i < maxCores; i++) {
            workingThreads[i] = new WorkingExplorers();
            workingThreads[i].start();
        }

        currentCore = 0;
    }

    private int width;
    private int height;

    private boolean[] wallMatrix;
    private Vec3[] visitMatrix;

    private int maxCores;
    private int currentCore;

    private WorkingExplorers[] workingThreads;

    private Object signalingObject;


    public Object getSignalingObject() {
        return signalingObject;
    }

    public void add(Explorer explorer) {
        this.workingThreads[(currentCore++) % maxCores].add(explorer);
    }

    public boolean done() {
        for (int i = 0; i < maxCores; i++)
            if (!this.workingThreads[i].isReady())
                return false;
        return true;
    }

    public Vec3[] getVisitMatrix() {
        return visitMatrix;
    }

    public boolean[] getWallMatrix() {
        return wallMatrix;
    }

    protected void setVisitMatrix(Vec3[] visitMatrix) {
        this.visitMatrix = visitMatrix;
    }

    protected void setWallMatrix(boolean[] wallMatrix) {
        this.wallMatrix = wallMatrix;
    }

    public int getWidth() {
        return width;
    }

    public int getHeight() {
        return height;
    }

    protected void setWidth(int width) {
        this.width = width;
    }

    protected void setHeight(int height) {
        this.height = height;
    }
}