package test;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertTrue;

import impl.Afficheur;
import impl.Canal;
import impl.CapteurImpl;
import impl.DiffusionSequentielle;
import impl.Scheduler;

public class TestAlgoDiffusionSeq {

    static int NB_CANAUX = 3;
    public static List<Integer>[] rSeq;



    private static void display(List<Integer>[] res){
        for(int i = 0; i< NB_CANAUX; i++){
            System.out.println("canal " + i + ":");
            for(int j = 0; j< res[i].size(); j++){
                System.out.print(res[i].get(j));
                if(j<res[i].size()-1) System.out.print(", ");
            }
            System.out.println(" ");
        }
    }

    @BeforeAll
    public static void testAtom() throws InterruptedException{

        ArrayList<Integer>[] r = new ArrayList[NB_CANAUX];
        for(int i = 0; i<NB_CANAUX; i++){
            r[i] = new ArrayList<Integer>();
        }

        Afficheur[] a = new Afficheur[NB_CANAUX];

        Scheduler scheduler = new Scheduler(NB_CANAUX);
        CapteurImpl c = new CapteurImpl();

        DiffusionSequentielle algo = new DiffusionSequentielle(c);
        c.setAlgoDiffusion(algo);

        for(int i = 0; i<NB_CANAUX; i++){
            Afficheur afficheur = new Afficheur();
            afficheur.setId(i);
            a[i] = afficheur;
            Canal canal = new Canal(c, scheduler, afficheur);
            c.attach(canal);
        }
         
        ScheduledExecutorService clock =  scheduler.getScheduler();
        ScheduledFuture<?> future = clock.scheduleAtFixedRate(() -> c.tick(), 0, 500, TimeUnit.MILLISECONDS);

        Thread.sleep(10000);
        System.out.println("STOP");
        System.out.println("waitting for lasts display...");
        future.cancel(false);
        Thread.sleep(3100); //3000ms max + 100ms de marge
        
        clock.shutdown();
        
        for(int i = 0; i<NB_CANAUX; i++){
            r[i] = a[i].vals;
        }
        rSeq = r;

        display(rSeq);
    }


    @Test
    void testGoodOrder(){
        boolean r = true;

        for(int i = 0; i< NB_CANAUX && r; i++){
            int test = 0;
            for(int j = 0; j< rSeq[i].size() && r; j++){
                r = r && rSeq[i].get(j) > test;
                test =  rSeq[i].get(j);
            }
        }
        assertTrue(r);
    }

    @Test
    void sameElements(){
        boolean r = true;

        for(int i = 0; i< NB_CANAUX-1 && r; i++){
            r = rSeq[i].size()==rSeq[i+1].size();
        }
        if(!r){
            System.err.println("Pas de la même taille !");
        }
        else{
            for(int j = 0; j< rSeq[0].size() && r; j++){
                int temp = rSeq[0].get(j);
                for(int i = 1; i< NB_CANAUX && r; i++){
                    r = r && rSeq[i].get(j)==temp;
                }
            }
        }
        assertTrue(r);
    }

}
