package fr.umlv.conc;

import java.util.OptionalDouble;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class AverageVote {
  private int party;
  private long sum;
  private int count;
  
  private ReentrantLock lock = new ReentrantLock();
  private Condition condition = lock.newCondition();
  
  public AverageVote(int party) {
    this.party = party;
  }
  
  public void vote(int value) throws InterruptedException {
    
    sum += value;
    count++;

  }
  
  public OptionalDouble average() {
    
    if (count == 0) {
      return OptionalDouble.empty();
    }
    return OptionalDouble.of(sum / (double)count);
    
  }
  
  public static void main(String[] args) {
    var vote = new AverageVote(5_000);
    new Thread(() -> {
      for (var start = System.currentTimeMillis(); System.currentTimeMillis() - start < 10_000;) {
        Thread.onSpinWait();
        vote.average().ifPresent(average -> {
          if (average != 256.0) {
            throw new AssertionError("average " + average);
          }
        });
      }
      System.out.println("end !");
    }).start();
    for (var i = 0; i < 5_000; i++) {
      new Thread(() -> {
        try {
          vote.vote(256);
        } catch (InterruptedException e) {
          // TODO !!
        }
        System.out.println(vote.average().orElseThrow());
      }).start();
    }
  }
}
