package be.iminds.ilabt.jfed.experimenter_gui.tasks;

import be.iminds.ilabt.jfed.highlevel.controller.TaskExecution;
import be.iminds.ilabt.jfed.highlevel.controller.TaskThread;
import be.iminds.ilabt.jfed.highlevel.model.SfaModel;
import be.iminds.ilabt.jfed.highlevel.tasks.HighLevelTaskFactory;
import be.iminds.ilabt.jfed.highlevel.tasks.ListSlicesTask;
import javafx.concurrent.Task;

import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;

/**
 * User: twalcari
 * Date: 3/18/2015
 * Time: 11:39
 */
public class FetchAllSlicesInfoTask extends Task<Void> {

    private final SfaModel sfaModel;
    private final HighLevelTaskFactory hltf;
    private final TaskThread tt;

    public FetchAllSlicesInfoTask(SfaModel sfaModel, HighLevelTaskFactory hltf, TaskThread tt) {
        this.sfaModel = sfaModel;

        this.hltf = hltf;
        this.tt = tt;
    }

    @Override
    protected Void call() throws Exception {
        updateMessage("Fetching all existing experiments");

        final ListSlicesTask refreshSlicesTask = hltf.listSlices();

        TaskExecution refreshTaskExecution = hltf.submitTask(refreshSlicesTask);

        while (!refreshTaskExecution.isCompleted()) {
            Thread.sleep(100);
        }

        updateMessage(String.format("Received %d experiments", refreshSlicesTask.getSlices().size()));

        List<be.iminds.ilabt.jfed.highlevel.controller.Task> extraTasks =
                sfaModel.getSlices().stream()
                        .filter(slice -> slice.getExpirationDate() == null)
                        .map(hltf::getAggregatesForSlice).collect(Collectors.toList());

        if (!extraTasks.isEmpty()) {

            updateMessage(String.format("Received %d experiments. Requesting extra info.", refreshSlicesTask.getSlices().size()));

            CountDownLatch latch = new CountDownLatch(extraTasks.size());

            for (be.iminds.ilabt.jfed.highlevel.controller.Task extraTask : extraTasks) {
                tt.addTask(extraTask, (task1, taskExecution, state) -> {
                    latch.countDown();
                    updateMessage(String.format("Received %d experiments. Requesting extra info (%d left).",
                            refreshSlicesTask.getSlices().size(), latch.getCount()));
                });
            }
            latch.await();
        }
        return null;
    }
}
