// Path: src/main/java/io/playpen/core/coordinator/PlayPen.java
// public abstract class PlayPen {
//     private static PlayPen instance = null;
// 
//     public static PlayPen get() {
//         return instance;
//     }
// 
//     // do not call except from Bootstrap
//     public static void reset() {
//         instance = null;
//     }
// 
//     public PlayPen() {
//         instance = this;
//     }
// 
//     public abstract String getServerId();
// 
//     public abstract CoordinatorMode getCoordinatorMode();
// 
//     public abstract PackageManager getPackageManager();
// 
//     public abstract PluginManager getPluginManager();
// 
//     public abstract ScheduledExecutorService getScheduler();
// 
//     public String generateId() {
//         return getServerId() + "-" + UUID.randomUUID().toString();
//     }
// 
//     public abstract boolean send(Protocol.Transaction message, String target);
// 
//     public abstract boolean receive(Protocol.AuthenticatedMessage auth, Channel from);
// 
//     public abstract boolean process(Commands.BaseCommand command, TransactionInfo info, String from);
// 
//     public abstract void onVMShutdown();
// }


import io.playpen.core.coordinator.PlayPen;
import io.playpen.core.protocol.Commands;
import io.playpen.core.protocol.Protocol;
import lombok.extern.log4j.Log4j2;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
package io.playpen.core.networking;



@Log4j2
public class TransactionManager {
    public static final long TRANSACTION_TIMEOUT = 340; // seconds

    private static TransactionManager instance = new TransactionManager();

    public static TransactionManager get() {
        return instance;
    }

    private Map<String, TransactionInfo> transactions = new ConcurrentHashMap<>();

    private TransactionManager() {}

    boolean isActive(String id) {
        return transactions.containsKey(id);
    }

    public TransactionInfo getTransaction(String id) {
        return transactions.get(id);
    }

    public Protocol.Transaction build(String id, Protocol.Transaction.Mode mode, Commands.BaseCommand command) {
        TransactionInfo info = getTransaction(id);
        if(info == null) {
            log.error("Unable to build unknown transaction " + id);
            return null;
        }

        return Protocol.Transaction.newBuilder()
                .setId(info.getId())
                .setMode(mode)
                .setPayload(command)
                .build();
    }

    public TransactionInfo begin() {
        TransactionInfo info = new TransactionInfo();

// Path: src/main/java/io/playpen/core/coordinator/PlayPen.java
// public abstract class PlayPen {
//     private static PlayPen instance = null;
// 
//     public static PlayPen get() {
//         return instance;
//     }
// 
//     // do not call except from Bootstrap
//     public static void reset() {
//         instance = null;
//     }
// 
//     public PlayPen() {
//         instance = this;
//     }
// 
//     public abstract String getServerId();
// 
//     public abstract CoordinatorMode getCoordinatorMode();
// 
//     public abstract PackageManager getPackageManager();
// 
//     public abstract PluginManager getPluginManager();
// 
//     public abstract ScheduledExecutorService getScheduler();
// 
//     public String generateId() {
//         return getServerId() + "-" + UUID.randomUUID().toString();
//     }
// 
//     public abstract boolean send(Protocol.Transaction message, String target);
// 
//     public abstract boolean receive(Protocol.AuthenticatedMessage auth, Channel from);
// 
//     public abstract boolean process(Commands.BaseCommand command, TransactionInfo info, String from);
// 
//     public abstract void onVMShutdown();
// }


// Path: src/main/java/io/playpen/core/networking/TransactionManager.java
import io.playpen.core.coordinator.PlayPen;
import io.playpen.core.protocol.Commands;
import io.playpen.core.protocol.Protocol;
import lombok.extern.log4j.Log4j2;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

package io.playpen.core.networking;



@Log4j2
public class TransactionManager {
    public static final long TRANSACTION_TIMEOUT = 340; // seconds

    private static TransactionManager instance = new TransactionManager();

    public static TransactionManager get() {
        return instance;
    }

    private Map<String, TransactionInfo> transactions = new ConcurrentHashMap<>();

    private TransactionManager() {}

    boolean isActive(String id) {
        return transactions.containsKey(id);
    }

    public TransactionInfo getTransaction(String id) {
        return transactions.get(id);
    }

    public Protocol.Transaction build(String id, Protocol.Transaction.Mode mode, Commands.BaseCommand command) {
        TransactionInfo info = getTransaction(id);
        if(info == null) {
            log.error("Unable to build unknown transaction " + id);
            return null;
        }

        return Protocol.Transaction.newBuilder()
                .setId(info.getId())
                .setMode(mode)
                .setPayload(command)
                .build();
    }

    public TransactionInfo begin() {
        TransactionInfo info = new TransactionInfo();

        info.setId(PlayPen.get().generateId());