// Path: src/main/java/epto/utils/Ball.java
// public class Ball extends HashMap<UUID, Event> {
// 
// }
// 
// Path: src/main/java/epto/utils/Event.java
// public class Event implements Comparable<Event>{
// 
//     public UUID id;
// 
//     public LogicalClock timestamp;
// 
//     public int ttl;
// 
//     public long sourceId;
// 
//     public Event() {
//         id = UUID.randomUUID();
//     }
// 
//     public int compareTo(Event o) {
//         int comparisionLC = timestamp.compareTo(o.timestamp);
//         return (comparisionLC != 0)? comparisionLC : (int)(sourceId - o.sourceId);
//     }
// 
//     @Override
//     public String toString() {
//         return "{timestamp=" + timestamp + ", ttl=" + ttl + ", sourceId=" + sourceId + "}";
//     }
// }
// 
// Path: src/main/java/epto/utils/Message.java
// public class Message {
// 
//     public final static int PREBROADCAST = 0;
//     public final static int BROADCAST = 1;
//     public final static int DELIVER = 2;
//     public final static int DISSEMINATION = 3;
//     public final static int ORDER = 4;
// 
//     private int type;
//     private Object content;
// //    private Node source;
// //    private Node destination;
// 
//     public Message(int type, Object content) {
//         this.type = type;
//         this.content = content;
//     }
// 
//     public int getType() {
//         return type;
//     }
// 
//     public void setType(int type) {
//         this.type = type;
//     }
// 
//     public Object getContent() {
//         return content;
//     }
// 
//     public void setContent(Object content) {
//         this.content = content;
//     }
// 
// //    public Node getSource() {
// //        return source;
// //    }
// //
// //    public void setSource(Node source) {
// //        this.source = source;
// //    }
// //
// //    public Node getDestination() {
// //        return destination;
// //    }
// //
// //    public void setDestination(Node destination) {
// //        this.destination = destination;
// //    }
// }
// 
// Path: src/main/java/epto/utils/Utils.java
// public class Utils {
// 
//     public static final int DEFAULT_FANOUT = 5;
// 
//     public static final int DEFAULT_TTL = 2;
// }
// 
// Path: src/main/java/pss/IPeerSamplingService.java
// public interface IPeerSamplingService {
// 
//     public Node selectNeighbor();
// 
//     public List<Node> selectNeighbors(int k);
// 
//     public int degree();
// 
//     public void myTurn(Node node, int pid);
// 
// }
// 
// Path: src/main/java/time/LogicalClock.java
// public class LogicalClock implements Comparable<LogicalClock> {
// 
//     private long nodeId;
//     private int eventId;
// 
//     public LogicalClock(long nodeId) {
//         this.nodeId = nodeId;
//         this.eventId = 0;
//     }
// 
//     public LogicalClock(long nodeId, int eventId) {
//         this(nodeId);
//         this.eventId = eventId;
//     }
// 
//     public void increment() {
//         this.eventId++;
//     }
// 
//     public long getNodeId() {
//         return nodeId;
//     }
// 
//     public void setNodeId(long nodeId) {
//         this.nodeId = nodeId;
//     }
// 
//     public int getEventId() {
//         return eventId;
//     }
// 
//     public void setEventId(int eventId) {
//         this.eventId = eventId;
//     }
// 
//     public int compareTo(LogicalClock o) {
//         return (nodeId == o.nodeId)? eventId - o.eventId : (int) nodeId - (int) o.nodeId;
//     }
// 
//     @Override
//     public String toString() {
//         return "{nodeId=" + nodeId + ", eventId=" + eventId + "}";
//     }
// 
//     @Override
//     public LogicalClock clone() throws CloneNotSupportedException {
//         return new LogicalClock(nodeId, eventId);
//     }
// }


import epto.utils.Ball;
import epto.utils.Event;
import epto.utils.Message;
import epto.utils.Utils;
import peersim.cdsim.CDProtocol;
import peersim.config.Configuration;
import peersim.config.FastConfig;
import peersim.core.Node;
import peersim.edsim.EDProtocol;
import peersim.transport.Transport;
import pss.IPeerSamplingService;
import time.LogicalClock;
import java.util.List;

//            case Message.PREBROADCAST: {
//                    EpTOBroadcast((Event) m.getContent(), node);
//                }
//                break;

            case Message.BROADCAST: {

                Ball ball = (Ball) m.getContent();

                // foreach event in ball do
                for (Event event : ball.values()) {
                    // if event.ttl < TTL then
                    if (event.ttl < TTL) {
                        // if event.id in nextBall then
                        if (nextBall.containsKey(event.id)) {
                            // if nextBall[event.id].ttl < event.ttl then
                            Event target = nextBall.get(event.id);
                            if (target.ttl < event.ttl) {
                                // update TTL
                                // nextBall[event.id].ttl = event.ttl
                                target.ttl = event.ttl;
                            }
                        } else {
                            // nextBall = nextBall U (event.id, event)
                            System.out.println("Node " + node.getID() + " has put in nextball : " + event);
                            nextBall.put(event.id, event);
                        }
                    }
                    // only needed with logical time
// Path: src/main/java/epto/utils/Ball.java
// public class Ball extends HashMap<UUID, Event> {
// 
// }
// 
// Path: src/main/java/epto/utils/Event.java
// public class Event implements Comparable<Event>{
// 
//     public UUID id;
// 
//     public LogicalClock timestamp;
// 
//     public int ttl;
// 
//     public long sourceId;
// 
//     public Event() {
//         id = UUID.randomUUID();
//     }
// 
//     public int compareTo(Event o) {
//         int comparisionLC = timestamp.compareTo(o.timestamp);
//         return (comparisionLC != 0)? comparisionLC : (int)(sourceId - o.sourceId);
//     }
// 
//     @Override
//     public String toString() {
//         return "{timestamp=" + timestamp + ", ttl=" + ttl + ", sourceId=" + sourceId + "}";
//     }
// }
// 
// Path: src/main/java/epto/utils/Message.java
// public class Message {
// 
//     public final static int PREBROADCAST = 0;
//     public final static int BROADCAST = 1;
//     public final static int DELIVER = 2;
//     public final static int DISSEMINATION = 3;
//     public final static int ORDER = 4;
// 
//     private int type;
//     private Object content;
// //    private Node source;
// //    private Node destination;
// 
//     public Message(int type, Object content) {
//         this.type = type;
//         this.content = content;
//     }
// 
//     public int getType() {
//         return type;
//     }
// 
//     public void setType(int type) {
//         this.type = type;
//     }
// 
//     public Object getContent() {
//         return content;
//     }
// 
//     public void setContent(Object content) {
//         this.content = content;
//     }
// 
// //    public Node getSource() {
// //        return source;
// //    }
// //
// //    public void setSource(Node source) {
// //        this.source = source;
// //    }
// //
// //    public Node getDestination() {
// //        return destination;
// //    }
// //
// //    public void setDestination(Node destination) {
// //        this.destination = destination;
// //    }
// }
// 
// Path: src/main/java/epto/utils/Utils.java
// public class Utils {
// 
//     public static final int DEFAULT_FANOUT = 5;
// 
//     public static final int DEFAULT_TTL = 2;
// }
// 
// Path: src/main/java/pss/IPeerSamplingService.java
// public interface IPeerSamplingService {
// 
//     public Node selectNeighbor();
// 
//     public List<Node> selectNeighbors(int k);
// 
//     public int degree();
// 
//     public void myTurn(Node node, int pid);
// 
// }
// 
// Path: src/main/java/time/LogicalClock.java
// public class LogicalClock implements Comparable<LogicalClock> {
// 
//     private long nodeId;
//     private int eventId;
// 
//     public LogicalClock(long nodeId) {
//         this.nodeId = nodeId;
//         this.eventId = 0;
//     }
// 
//     public LogicalClock(long nodeId, int eventId) {
//         this(nodeId);
//         this.eventId = eventId;
//     }
// 
//     public void increment() {
//         this.eventId++;
//     }
// 
//     public long getNodeId() {
//         return nodeId;
//     }
// 
//     public void setNodeId(long nodeId) {
//         this.nodeId = nodeId;
//     }
// 
//     public int getEventId() {
//         return eventId;
//     }
// 
//     public void setEventId(int eventId) {
//         this.eventId = eventId;
//     }
// 
//     public int compareTo(LogicalClock o) {
//         return (nodeId == o.nodeId)? eventId - o.eventId : (int) nodeId - (int) o.nodeId;
//     }
// 
//     @Override
//     public String toString() {
//         return "{nodeId=" + nodeId + ", eventId=" + eventId + "}";
//     }
// 
//     @Override
//     public LogicalClock clone() throws CloneNotSupportedException {
//         return new LogicalClock(nodeId, eventId);
//     }
// }


// Path: src/main/java/epto/EpTODissemination.java
import epto.utils.Ball;
import epto.utils.Event;
import epto.utils.Message;
import epto.utils.Utils;
import peersim.cdsim.CDProtocol;
import peersim.config.Configuration;
import peersim.config.FastConfig;
import peersim.core.Node;
import peersim.edsim.EDProtocol;
import peersim.transport.Transport;
import pss.IPeerSamplingService;
import time.LogicalClock;
import java.util.List;


//            case Message.PREBROADCAST: {
//                    EpTOBroadcast((Event) m.getContent(), node);
//                }
//                break;

            case Message.BROADCAST: {

                Ball ball = (Ball) m.getContent();

                // foreach event in ball do
                for (Event event : ball.values()) {
                    // if event.ttl < TTL then
                    if (event.ttl < TTL) {
                        // if event.id in nextBall then
                        if (nextBall.containsKey(event.id)) {
                            // if nextBall[event.id].ttl < event.ttl then
                            Event target = nextBall.get(event.id);
                            if (target.ttl < event.ttl) {
                                // update TTL
                                // nextBall[event.id].ttl = event.ttl
                                target.ttl = event.ttl;
                            }
                        } else {
                            // nextBall = nextBall U (event.id, event)
                            System.out.println("Node " + node.getID() + " has put in nextball : " + event);
                            nextBall.put(event.id, event);
                        }
                    }
                    // only needed with logical time
                    try {