// Path: src/main/java/com/maxdemarzi/RelationshipTypes.java
// public enum  RelationshipTypes implements RelationshipType {
//     BLOCKS,
//     FOLLOWS,
//     MUTES,
//     LIKES,
//     REPLIED_TO
// }
// 
// Path: src/main/java/com/maxdemarzi/Properties.java
// public final class Properties {
// 
//     private Properties() {
//         throw new IllegalAccessError("Utility class");
//     }
// 
//     public static final String COUNT = "count";
//     public static final String EMAIL = "email";
//     public static final String FOLLOWERS_YOU_KNOW = "followers_you_know";
//     public static final String FOLLOWERS_YOU_KNOW_COUNT = "followers_you_know_count";
//     public static final String HASH = "hash";
//     public static final String I_FOLLOW = "i_follow";
//     public static final String FOLLOWS_ME = "follows_me";
//     public static final String LIKES = "likes";
//     public static final String LIKED = "liked";
//     public static final String LIKED_TIME = "liked_time";
//     public static final String NAME = "name";
//     public static final String PASSWORD = "password";
//     public static final String USERNAME = "username";
//     public static final String REPOSTS = "reposts";
//     public static final String REPOSTED = "reposted";
//     public static final String REPOSTED_TIME = "reposted_time";
//     public static final String REPOSTER_NAME = "reposter_name";
//     public static final String REPOSTER_USERNAME = "reposter_username";
//     public static final String STATUS = "status";
//     public static final String TIME = "time";
// 
// }
// 
// Path: src/main/java/com/maxdemarzi/Time.java
// public static Long getLatestTime(@QueryParam("since") Long since) {
//     LocalDateTime dateTime;
//     if (since == null) {
//         dateTime = LocalDateTime.now(utc);
//     } else {
//         dateTime = LocalDateTime.ofEpochSecond(since, 0, ZoneOffset.UTC);
//     }
//     return dateTime.toEpochSecond(ZoneOffset.UTC);
// }
// 
// Path: src/main/java/com/maxdemarzi/Time.java
// public static final ZoneId utc = TimeZone.getTimeZone("UTC").toZoneId();
// 
// Path: src/main/java/com/maxdemarzi/users/Users.java
// public static Node findUser(String username, Transaction tx) {
//     if (username == null) { return null; }
//     Node user = tx.findNode(Labels.User, USERNAME, username);
//     if (user == null) { throw UserExceptions.userNotFound(); }
//     return user;
// }
// 
// Path: src/main/java/com/maxdemarzi/users/Users.java
// public static Map<String, Object> getUserAttributes(Node user) {
//     Map<String, Object> results;
//     results = user.getAllProperties();
//     results.remove(EMAIL);
//     results.remove(PASSWORD);
//     Integer following = user.getDegree(RelationshipTypes.FOLLOWS, Direction.OUTGOING);
//     Integer followers = user.getDegree(RelationshipTypes.FOLLOWS, Direction.INCOMING);
//     Integer likes = user.getDegree(RelationshipTypes.LIKES, Direction.OUTGOING);
//     Integer posts = user.getDegree(Direction.OUTGOING) - following - likes;
//     results.put("following", following);
//     results.put("followers", followers);
//     results.put("likes", likes);
//     results.put("posts", posts);
//     return results;
// }


import com.fasterxml.jackson.databind.ObjectMapper;
import com.maxdemarzi.RelationshipTypes;
import org.neo4j.dbms.api.DatabaseManagementService;
import org.neo4j.graphdb.*;
import javax.ws.rs.Path;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Map;
import static com.maxdemarzi.Properties.*;
import static com.maxdemarzi.Time.getLatestTime;
import static com.maxdemarzi.Time.utc;
import static com.maxdemarzi.users.Users.findUser;
import static com.maxdemarzi.users.Users.getUserAttributes;
import static java.util.Collections.reverseOrder;
        try (Transaction tx = db.beginTx()) {
            Node user = findUser(username, tx);
            for (Relationship r1: user.getRelationships(Direction.OUTGOING, RelationshipTypes.BLOCKS)) {
                Node blocked = r1.getEndNode();
                Long time = (Long)r1.getProperty("time");
                if(time < latest) {
                    Map<String, Object> result = getUserAttributes(blocked);
                    result.put(TIME, time);
                    results.add(result);
                }
            }
            tx.commit();
        }
        results.sort(Comparator.comparing(m -> (Long) m.get(TIME), reverseOrder()));
        return Response.ok().entity(objectMapper.writeValueAsString(
                results.subList(0, Math.min(results.size(), limit))))
                .build();

    }

    @POST
    @Path("/{username2}")
    public Response createBlocks(@PathParam("username") final String username,
                                  @PathParam("username2") final String username2) throws IOException {
        Map<String, Object> results;
        try (Transaction tx = db.beginTx()) {
            Node user = findUser(username, tx);
            Node user2 = findUser(username2, tx);

            if (user.getDegree(RelationshipTypes.BLOCKS, Direction.OUTGOING)
// Path: src/main/java/com/maxdemarzi/RelationshipTypes.java
// public enum  RelationshipTypes implements RelationshipType {
//     BLOCKS,
//     FOLLOWS,
//     MUTES,
//     LIKES,
//     REPLIED_TO
// }
// 
// Path: src/main/java/com/maxdemarzi/Properties.java
// public final class Properties {
// 
//     private Properties() {
//         throw new IllegalAccessError("Utility class");
//     }
// 
//     public static final String COUNT = "count";
//     public static final String EMAIL = "email";
//     public static final String FOLLOWERS_YOU_KNOW = "followers_you_know";
//     public static final String FOLLOWERS_YOU_KNOW_COUNT = "followers_you_know_count";
//     public static final String HASH = "hash";
//     public static final String I_FOLLOW = "i_follow";
//     public static final String FOLLOWS_ME = "follows_me";
//     public static final String LIKES = "likes";
//     public static final String LIKED = "liked";
//     public static final String LIKED_TIME = "liked_time";
//     public static final String NAME = "name";
//     public static final String PASSWORD = "password";
//     public static final String USERNAME = "username";
//     public static final String REPOSTS = "reposts";
//     public static final String REPOSTED = "reposted";
//     public static final String REPOSTED_TIME = "reposted_time";
//     public static final String REPOSTER_NAME = "reposter_name";
//     public static final String REPOSTER_USERNAME = "reposter_username";
//     public static final String STATUS = "status";
//     public static final String TIME = "time";
// 
// }
// 
// Path: src/main/java/com/maxdemarzi/Time.java
// public static Long getLatestTime(@QueryParam("since") Long since) {
//     LocalDateTime dateTime;
//     if (since == null) {
//         dateTime = LocalDateTime.now(utc);
//     } else {
//         dateTime = LocalDateTime.ofEpochSecond(since, 0, ZoneOffset.UTC);
//     }
//     return dateTime.toEpochSecond(ZoneOffset.UTC);
// }
// 
// Path: src/main/java/com/maxdemarzi/Time.java
// public static final ZoneId utc = TimeZone.getTimeZone("UTC").toZoneId();
// 
// Path: src/main/java/com/maxdemarzi/users/Users.java
// public static Node findUser(String username, Transaction tx) {
//     if (username == null) { return null; }
//     Node user = tx.findNode(Labels.User, USERNAME, username);
//     if (user == null) { throw UserExceptions.userNotFound(); }
//     return user;
// }
// 
// Path: src/main/java/com/maxdemarzi/users/Users.java
// public static Map<String, Object> getUserAttributes(Node user) {
//     Map<String, Object> results;
//     results = user.getAllProperties();
//     results.remove(EMAIL);
//     results.remove(PASSWORD);
//     Integer following = user.getDegree(RelationshipTypes.FOLLOWS, Direction.OUTGOING);
//     Integer followers = user.getDegree(RelationshipTypes.FOLLOWS, Direction.INCOMING);
//     Integer likes = user.getDegree(RelationshipTypes.LIKES, Direction.OUTGOING);
//     Integer posts = user.getDegree(Direction.OUTGOING) - following - likes;
//     results.put("following", following);
//     results.put("followers", followers);
//     results.put("likes", likes);
//     results.put("posts", posts);
//     return results;
// }


// Path: src/main/java/com/maxdemarzi/blocks/Blocks.java
import com.fasterxml.jackson.databind.ObjectMapper;
import com.maxdemarzi.RelationshipTypes;
import org.neo4j.dbms.api.DatabaseManagementService;
import org.neo4j.graphdb.*;
import javax.ws.rs.Path;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Map;
import static com.maxdemarzi.Properties.*;
import static com.maxdemarzi.Time.getLatestTime;
import static com.maxdemarzi.Time.utc;
import static com.maxdemarzi.users.Users.findUser;
import static com.maxdemarzi.users.Users.getUserAttributes;
import static java.util.Collections.reverseOrder;

        try (Transaction tx = db.beginTx()) {
            Node user = findUser(username, tx);
            for (Relationship r1: user.getRelationships(Direction.OUTGOING, RelationshipTypes.BLOCKS)) {
                Node blocked = r1.getEndNode();
                Long time = (Long)r1.getProperty("time");
                if(time < latest) {
                    Map<String, Object> result = getUserAttributes(blocked);
                    result.put(TIME, time);
                    results.add(result);
                }
            }
            tx.commit();
        }
        results.sort(Comparator.comparing(m -> (Long) m.get(TIME), reverseOrder()));
        return Response.ok().entity(objectMapper.writeValueAsString(
                results.subList(0, Math.min(results.size(), limit))))
                .build();

    }

    @POST
    @Path("/{username2}")
    public Response createBlocks(@PathParam("username") final String username,
                                  @PathParam("username2") final String username2) throws IOException {
        Map<String, Object> results;
        try (Transaction tx = db.beginTx()) {
            Node user = findUser(username, tx);
            Node user2 = findUser(username2, tx);

            if (user.getDegree(RelationshipTypes.BLOCKS, Direction.OUTGOING)
                    < user2.getDegree(RelationshipTypes.BLOCKS, Direction.INCOMING) ) {