package core.framework.impl.log;

import core.framework.util.Encodings;

import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author neo
 */
class ActionId {
    private static final AtomicInteger COUNTER = new AtomicInteger(ThreadLocalRandom.current().nextInt());
    private static final int LOW_ORDER_THREE_BYTES = 0xFFFFFF;
    private static final int MACHINE_IDENTIFIER = machineIdentifier() & LOW_ORDER_THREE_BYTES;

    private static int machineIdentifier() {
        try {
            var builder = new StringBuilder();
            Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
            while (networkInterfaces.hasMoreElements()) {
                NetworkInterface networkInterface = networkInterfaces.nextElement();
                builder.append(networkInterface.getName());
                byte[] mac = networkInterface.getHardwareAddress();
                if (mac != null) builder.append(Encodings.hex(mac));
            }
            builder.append(ThreadLocalRandom.current().nextInt());  // append random value in case multiple apps run on same server (which is highly unlikely with cloud/kube env)
            return builder.toString().hashCode();
        } catch (SocketException e) {
            throw new Error(e);
        }
    }

    // action id doesn't need strict uniqueness as UUID, here to generate shorter and more elasticsearch/lucene friendly id
    static String next() {
        long timeInMs = System.currentTimeMillis();
        int counter = COUNTER.getAndIncrement() & LOW_ORDER_THREE_BYTES;
        byte[] bytes = new byte[10];
        bytes[0] = (byte) (timeInMs >> 32);     // save 5 bytes time in ms, about 17 years value space
        bytes[1] = (byte) (timeInMs >> 24);
        bytes[2] = (byte) (timeInMs >> 16);
        bytes[3] = (byte) (timeInMs >> 8);
        bytes[4] = (byte) (timeInMs);
        bytes[5] = (byte) (MACHINE_IDENTIFIER >> 16);   // 3 bytes as machine id, about 16M value space
        bytes[6] = (byte) (MACHINE_IDENTIFIER >> 8);
        bytes[7] = (byte) (MACHINE_IDENTIFIER);
        bytes[8] = (byte) (counter >> 8);               // 2 bytes for max 65535 actions per ms per server
        bytes[9] = (byte) (counter);
        return Encodings.hex(bytes);
    }
}

@@ -2019,25 +2019,24 @@
  (byte) 
-(
 timeInMs
 );%0A     
@@ -2027,17 +2027,16 @@
 timeInMs
-)
 ;%0A      
@@ -2204,33 +2204,32 @@
 tes%5B7%5D = (byte) 
-(
 MACHINE_IDENTIFI
@@ -2230,17 +2230,16 @@
 ENTIFIER
-)
 ;%0A      
@@ -2369,17 +2369,15 @@
 te) 
-(
 counter
-)
 ;%0A  

fix checkstyle