package org.mwdb.task.action;

import org.mwdb.*;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;

public class ActionTraverse implements KTaskAction {

    private final String _name;

    public ActionTraverse(final String p_name) {
        this._name = p_name;
    }

    @Override
    public final void eval(final KTaskContext context) {
        Object previousResult = context.getPreviousResult();
        if (previousResult != null) {
            //dry execute to count waiter
            Set<Long> toLoad = new HashSet<Long>();
            if (previousResult instanceof KNode[]) {
                collectNodeArray((KNode[]) previousResult, toLoad);
            } else if (previousResult instanceof Object[]) {
                collectArray((Object[]) previousResult, toLoad);
            } else if (previousResult instanceof KNode) {
                KNode loop = (KNode) previousResult;
                Object rel = loop.att(_name);
                if (rel != null && rel instanceof long[]) {
                    long[] interResult = (long[]) rel;
                    for (int j = 0; j < interResult.length; j++) {
                        toLoad.add(interResult[j]);
                    }
                }
            }
            if (!toLoad.isEmpty()) {
                KDeferCounter deferCounter = context.graph().counter(toLoad.size());
                final KNode[] resultNodes = new KNode[toLoad.size()];
                final AtomicInteger cursor = new AtomicInteger();
                for (Long idNode : toLoad) {
                    context.graph().lookup(context.getWorld(), context.getTime(), idNode, new KCallback<KNode>() {
                        @Override
                        public void on(KNode result) {
                            resultNodes[cursor.getAndIncrement()] = result;
                            deferCounter.count();
                        }
                    });
                }
                deferCounter.then(new KCallback() {
                    @Override
                    public void on(Object result) {
                        context.setResult(resultNodes);
                        context.next();
                    }
                });
            } else {
                context.next();
            }
        } else {
            context.next();
        }
    }

    private void collectArray(Object[] current, Set<Long> toLoad) {
        for (int i = 0; i < current.length; i++) {
            if (current[i] instanceof KNode[]) {
                collectNodeArray((KNode[]) current[i], toLoad);
            } else if (current[i] instanceof Object[]) {
                collectArray((Object[]) current[i], toLoad);
            } else if (current[i] instanceof KNode) {
                KNode loop = (KNode) current[i];
                Object rel = loop.att(_name);
                if (rel != null && rel instanceof long[]) {
                    long[] interResult = (long[]) rel;
                    for (int j = 0; j < interResult.length; j++) {
                        toLoad.add(interResult[j]);
                    }
                }
            }
        }
    }

    private void collectNodeArray(KNode[] current, Set<Long> toLoad) {
        for (int i = 0; i < current.length; i++) {
            if (current[i] != null) {
                Object rel = current[i].att(_name);
                if (rel != null && rel instanceof long[]) {
                    long[] interResult = (long[]) rel;
                    for (int j = 0; j < interResult.length; j++) {
                        toLoad.add(interResult[j]);
                    }
                }
            }
        }
    }

}

@@ -1275,49 +1275,9 @@
   %7D%0A
-            if (!toLoad.isEmpty()) %7B%0A    
+%0A
     
@@ -1361,28 +1361,24 @@
             
-    
 final KNode%5B
@@ -1427,28 +1427,24 @@
             
- 
-   
 final Atomic
@@ -1489,28 +1489,24 @@
             
-    
 for (Long id
@@ -1518,28 +1518,24 @@
 : toLoad) %7B%0A
-    
             
@@ -1645,36 +1645,32 @@
                 
- 
-   
 @Override%0A      
@@ -1655,36 +1655,32 @@
       @Override%0A
-    
                 
@@ -1706,36 +1706,32 @@
 KNode result) %7B%0A
-    
                 
@@ -1802,36 +1802,32 @@
                 
-    
 deferCounter.cou
@@ -1848,33 +1848,26 @@
             
-    %7D%0A   
+%7D%0A
             
@@ -1862,33 +1862,32 @@
                 
- 
 %7D);%0A            
@@ -1882,34 +1882,26 @@
             
-    %7D%0A    
+%7D%0A
             
@@ -1944,36 +1944,32 @@
                 
-  
-  
 @Override%0A      
@@ -1954,36 +1954,32 @@
       @Override%0A
-    
                 
@@ -2022,36 +2022,32 @@
                 
-    
 context.setResul
@@ -2074,36 +2074,32 @@
                 
-  
-  
 context.next();%0A
@@ -2110,34 +2110,26 @@
             
-    %7D%0A    
+%7D%0A
             
@@ -2136,75 +2136,8 @@
 %7D);%0A
-            %7D else %7B%0A                context.next();%0A            %7D%0A
     

fix ActionTraverse: put an empty array in the result if there is no element in the relation