package org.umlg.sqlg.step.barrier;

import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
import org.apache.tinkerpop.gremlin.process.traversal.util.FastNoSuchElementException;
import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
import org.umlg.sqlg.step.SqlgAbstractStep;
import org.umlg.sqlg.structure.traverser.SqlgTraverserGenerator;

import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * @author Pieter Martin (https://github.com/pietermartin)
 * Date: 2019/07/04
 */
@SuppressWarnings("unchecked")
public abstract class SqlgReducingStepBarrier<S, E> extends SqlgAbstractStep<S, E> {

    private boolean first = true;
    private E result = null;
    private Iterator<Traverser.Admin<E>> resultIterator = null;

    SqlgReducingStepBarrier(Traversal.Admin<?, ?> traversal) {
        super(traversal);
    }

    @Override
    protected Traverser.Admin<E> processNextStart() throws NoSuchElementException {
        if (this.first) {
            this.first = false;
            while (this.starts.hasNext()) {
                Traverser.Admin<S> s = this.starts.next();
                this.result = reduce(result, s.get());
            }
            Traverser.Admin<E> traverser = produceFinalResult(result);
            this.resultIterator = IteratorUtils.asIterator(traverser);
        }
        if (this.resultIterator.hasNext()) {
            return this.resultIterator.next();
        } else {
            reset();
            throw FastNoSuchElementException.instance();
        }
    }

    protected Traverser.Admin<E> produceFinalResult(E result) {
        return SqlgTraverserGenerator.instance().generate(result, this, 1L, false, false);
    }

    public E reduce(E a, S b) {
        //noop
        throw new IllegalStateException("noop");
    }

//    public MeanGlobalStep.MeanNumber reduce(MeanGlobalStep.MeanNumber meanNumber, Pair<Number, Long> bPair) {
//        //noop
//        throw new IllegalStateException("noop");
//    }
}

@@ -1239,32 +1239,157 @@
 ;%0A            %7D%0A
+            if (this.result == null) %7B%0A                throw FastNoSuchElementException.instance();%0A            %7D else %7B%0A    
             Trav
@@ -1443,16 +1443,20 @@
 esult);%0A
+    
         
@@ -1518,16 +1518,30 @@
 erser);%0A
+            %7D%0A
         
@@ -1573,16 +1573,47 @@
 Iterator
+ != null && this.resultIterator
 .hasNext
@@ -1971,31 +1971,16 @@
  S b) %7B%0A
-        //noop%0A
         
@@ -2031,194 +2031,6 @@
  %7D%0A%0A
-//    public MeanGlobalStep.MeanNumber reduce(MeanGlobalStep.MeanNumber meanNumber, Pair%3CNumber, Long%3E bPair) %7B%0A//        //noop%0A//        throw new IllegalStateException(%22noop%22);%0A//    %7D%0A
 %7D%0A

handle null