package CipherCracker;

import it.unimi.dsi.fastutil.ints.IntList;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;


public class ThreadManager {
    public static IntList manager(HashSet<IntSequence> localCheckSet, ArrayList<Integer> localKeysArray, ArrayList<Integer> localKeysPositions, ArrayList<String> localCipherText) {
        int threads = Runtime.getRuntime().availableProcessors();
        //int threads = 2;
        int numPartitions = threads;
        ExecutorService pool = Executors.newFixedThreadPool(threads);

        List<ArrayList<Integer>> partitions = new ArrayList<>();

        int totalItems = localKeysPositions.size();
        int baseSize = totalItems / numPartitions;
        int remainder = totalItems % numPartitions;

        // The List partitioner
        int start = 0;
        for (int i = 0; i < numPartitions; i++) {
            // Distribute the remainder items across the initial partitions
            int currentPartitionSize = baseSize + (i < remainder ? 1 : 0);
            int end = start + currentPartitionSize;

            // Ensure we don't out-of-bounds check if the list is smaller than numPartitions
            if (start < totalItems) {
                partitions.add(new ArrayList<>(localKeysPositions.subList(start, end)));
            } else {
                partitions.add(new ArrayList<>()); // Add empty list if no items left
            }

            start = end;
        }

        // Manages thread task creation
        List<Future<IntList>> futures = new ArrayList<>();
        for (int i = 0; i < threads; i++) {
            ThreadTask task = new ThreadTask();
            int finalI = i;
            Future<IntList> future = pool.submit(() -> task.primaryKeyFinder(localCheckSet, localKeysArray, partitions.get(finalI), localCipherText));
            futures.add(future);
        }

        // Waits for the thread to finish and returns the IntList
        for (int i = 0; i < threads; i++) {
            try {
                IntList actualList = futures.get(i).get();
                if (actualList != null) {
                    pool.shutdown();
                    return actualList;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        // Shuts down the pool
        pool.shutdown();
        return null;
    }
}