import java.util.*;
public class DistSensor extends Process implements Runnable,Sensor {
    final static int red = 0, green = 1;
    int candidate[], color[],G[];
    boolean finished = false, haveToken = false;
    LinkedList q = new LinkedList();
    SensorUser app;
    public DistSensor(VCLinker initComm, SensorUser app) {
        super(initComm);
        this.app = app;
        candidate = new int[N]; color = new int[N]; G = new int[N];
        for (int j=0; j<N; j++)    { color[j] = red; G[j] = 0;}
        if (myId==Symbols.coordinator) haveToken=true;
        new Thread(this).start();
    }
    public synchronized void run(){
        while (!finished) {
            while (!haveToken) myWait();
            handleToken();
        }
    }
    public synchronized void handleToken() {
        while (color[myId] == red) {
            while (q.isEmpty() && !finished) myWait();
            if (q.isEmpty() && finished) {
                app.globalPredicateFalse(myId);
                return;
            }
            candidate = (int[]) q.removeFirst();
            if (candidate[myId] > G[myId]) {
                G[myId] = candidate[myId]; color[myId] = green;
            }
        }
        for (int j = 0; j < N; j++)
            if ((j != myId) && (candidate[j] >= G[j])) {
                G[j] = candidate[j]; color[j] = red;
            }
        int j = Util.searchArray(color, red);
        if (j != -1) sendToken(j);
        else {
            app.globalPredicateTrue(G);
            finished = true;
        }
    }
    public synchronized void handleMsg(Message m, int source, String tag) {
        if (tag.equals("TokenG")) Util.readArray(m.getMessage(), G);
        else if (tag.equals("Tokencolor")) {
            Util.readArray(m.getMessage(), color);
            haveToken = true;
            notifyAll();
        } else if (tag.equals("finished")) finished = true;
    }
    void sendToken(int j) {
       ((VCLinker) comm).simpleSendMsg(j, "TokenG", Util.writeArray(G));
       ((VCLinker) comm).simpleSendMsg(j,"Tokencolor",Util.writeArray(color));
       haveToken = false;
    }
    public synchronized void localPredicateTrue(VectorClock vc) {
        q.add(vc.v);
        notifyAll();
    }
}