// Path: src/main/java/com/maxdemarzi/processing/NodeCounter.java
// public class NodeCounter {
//     public int getNodeCount(GraphDatabaseService db) {
//         Result result = db.execute( "MATCH (n) RETURN max(id(n)) AS maxId" );
//         return ((Number) result.next().get( "maxId" )).intValue() + 1;
// 
//     }
//     public int getRelationshipCount(GraphDatabaseService db) {
//         Result result = db.execute( "MATCH ()-[r]->() RETURN max(id(r)) AS maxId" );
//         return ((Number) result.next().get( "maxId" )).intValue() + 1;
//     }
// }
// 
// Path: src/main/java/com/maxdemarzi/processing/OpsRunner.java
// public interface OpsRunner {
//     void run(int node) throws EntityNotFoundException;
// }
// 
// Path: src/main/java/com/maxdemarzi/processing/Utils.java
// public static void runOperations(ExecutorService pool, final PrimitiveLongIterator it, int totalCount, ReadOperations ops, OpsRunner runner) {
//     List<Future> futures = new ArrayList<>((int)(totalCount / BATCH_SIZE));
//     while (it.hasNext()) {
//         futures.add(pool.submit(new BatchRunnable(ops, it, BATCH_SIZE,runner)));
//     }
//     Utils.waitForTasks(futures);
// }


import com.maxdemarzi.processing.NodeCounter;
import com.maxdemarzi.processing.OpsRunner;
import org.neo4j.collection.primitive.PrimitiveLongIterator;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Transaction;
import org.neo4j.kernel.internal.GraphDatabaseAPI;
import org.neo4j.kernel.api.ReadOperations;
import org.neo4j.kernel.api.exceptions.EntityNotFoundException;
import org.neo4j.kernel.impl.core.ThreadToStatementContextBridge;
import java.util.Arrays;
import java.util.concurrent.ExecutorService;
import static com.maxdemarzi.processing.Utils.runOperations;
package com.maxdemarzi.processing.centrality;



public class DegreeArrayStorageParallelSPI implements Centrality {
    private final GraphDatabaseAPI db;
    private final int nodeCount;
    private final ExecutorService pool;
    private int[] degree;
    private String directionName = "";
    private final Direction direction;

    public DegreeArrayStorageParallelSPI(GraphDatabaseService db, ExecutorService pool, Direction direction) {
        this.pool = pool;
        this.db = (GraphDatabaseAPI)db;
        this.nodeCount = new NodeCounter().getNodeCount(db);
        this.direction = direction;
        if (!direction.equals(Direction.BOTH)) {
            directionName = direction.name().toLowerCase() + "_";
        }
    }

    @Override
    public void compute(String label, String type, int iterations) {
        degree = new int[nodeCount];
        Arrays.fill(degree, -1);

        try ( Transaction tx = db.beginTx()) {
            ThreadToStatementContextBridge ctx = this.db.getDependencyResolver().resolveDependency(ThreadToStatementContextBridge.class);
            ReadOperations ops = ctx.get().readOperations();
            int labelId = ops.labelGetForName(label);
            int relationshipTypeId = ops.relationshipTypeGetForName(type);

            PrimitiveLongIterator it = ops.nodesGetForLabel(labelId);
            int totalCount = nodeCount;
// Path: src/main/java/com/maxdemarzi/processing/NodeCounter.java
// public class NodeCounter {
//     public int getNodeCount(GraphDatabaseService db) {
//         Result result = db.execute( "MATCH (n) RETURN max(id(n)) AS maxId" );
//         return ((Number) result.next().get( "maxId" )).intValue() + 1;
// 
//     }
//     public int getRelationshipCount(GraphDatabaseService db) {
//         Result result = db.execute( "MATCH ()-[r]->() RETURN max(id(r)) AS maxId" );
//         return ((Number) result.next().get( "maxId" )).intValue() + 1;
//     }
// }
// 
// Path: src/main/java/com/maxdemarzi/processing/OpsRunner.java
// public interface OpsRunner {
//     void run(int node) throws EntityNotFoundException;
// }
// 
// Path: src/main/java/com/maxdemarzi/processing/Utils.java
// public static void runOperations(ExecutorService pool, final PrimitiveLongIterator it, int totalCount, ReadOperations ops, OpsRunner runner) {
//     List<Future> futures = new ArrayList<>((int)(totalCount / BATCH_SIZE));
//     while (it.hasNext()) {
//         futures.add(pool.submit(new BatchRunnable(ops, it, BATCH_SIZE,runner)));
//     }
//     Utils.waitForTasks(futures);
// }


// Path: src/main/java/com/maxdemarzi/processing/centrality/DegreeArrayStorageParallelSPI.java
import com.maxdemarzi.processing.NodeCounter;
import com.maxdemarzi.processing.OpsRunner;
import org.neo4j.collection.primitive.PrimitiveLongIterator;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Transaction;
import org.neo4j.kernel.internal.GraphDatabaseAPI;
import org.neo4j.kernel.api.ReadOperations;
import org.neo4j.kernel.api.exceptions.EntityNotFoundException;
import org.neo4j.kernel.impl.core.ThreadToStatementContextBridge;
import java.util.Arrays;
import java.util.concurrent.ExecutorService;
import static com.maxdemarzi.processing.Utils.runOperations;

package com.maxdemarzi.processing.centrality;



public class DegreeArrayStorageParallelSPI implements Centrality {
    private final GraphDatabaseAPI db;
    private final int nodeCount;
    private final ExecutorService pool;
    private int[] degree;
    private String directionName = "";
    private final Direction direction;

    public DegreeArrayStorageParallelSPI(GraphDatabaseService db, ExecutorService pool, Direction direction) {
        this.pool = pool;
        this.db = (GraphDatabaseAPI)db;
        this.nodeCount = new NodeCounter().getNodeCount(db);
        this.direction = direction;
        if (!direction.equals(Direction.BOTH)) {
            directionName = direction.name().toLowerCase() + "_";
        }
    }

    @Override
    public void compute(String label, String type, int iterations) {
        degree = new int[nodeCount];
        Arrays.fill(degree, -1);

        try ( Transaction tx = db.beginTx()) {
            ThreadToStatementContextBridge ctx = this.db.getDependencyResolver().resolveDependency(ThreadToStatementContextBridge.class);
            ReadOperations ops = ctx.get().readOperations();
            int labelId = ops.labelGetForName(label);
            int relationshipTypeId = ops.relationshipTypeGetForName(type);

            PrimitiveLongIterator it = ops.nodesGetForLabel(labelId);
            int totalCount = nodeCount;
            runOperations(pool, it, totalCount, ops, new OpsRunner() {