package cs451.tools;

import cs451.net.NetManager;
import cs451.parser.Host;
import cs451.parser.Parser;

/**
 * Automatically Detects best parameters for the system
 */
public abstract class ParamDetector {

    private static Integer bound(Integer value, Integer lower, Integer upper){
        return Math.min(Math.max(value,lower),upper);
    }

    public static void detectAndSet(Host me, Parser p){

        int cores = Runtime.getRuntime().availableProcessors();
        int SMProcesses = Math.toIntExact(p.hosts().stream().filter(h -> h.getIp().equals(me.getIp())).count());
        int coresPerProcess = bound((cores/SMProcesses)+1,2,64);
        int bonusCoresPerProcess = SMProcesses == 1 ? 2: 1;

        System.out.println("System has "+cores+" cores, shared by "+SMProcesses+" processes.");
        if(cores/SMProcesses < 2){
            System.out.println("Running too many processes on the same System might degrade performance.");
        }
        System.out.println("Starting Process with "+coresPerProcess+" cores and "+bonusCoresPerProcess+" bonus cores.");
        NetManager.THREAD_COUNT = coresPerProcess;
        NetManager.THREAD_BOOST_COUNT = bonusCoresPerProcess;

        int messages = p.messageCount();
        int processCount = p.hosts().size();
        int windowWidthMult = Math.toIntExact(Math.round(Math.pow(2.0,(5-(processCount/5.0)))));
        int windowWidth = bound(coresPerProcess*windowWidthMult,4,messages);

        System.out.println("Process expected to broadcast "+messages+" messages.");
        System.out.println("Starting Process with WindowWidth of "+windowWidth+" (~ x"+windowWidthMult+").");
        NetManager.WINDOW_WIDTH = windowWidth;

        NetManager.INTERNAL_WAIT = 500;

        //We might want to PingPong To set Custom Timing Limitations....
        NetManager.FD_MAX_TRIES = 10;
        NetManager.FD_WAIT = 1000;
    }
}
