package tech.tablesaw.columns.numbers;

import it.unimi.dsi.fastutil.doubles.DoubleArrayList;
import it.unimi.dsi.fastutil.doubles.DoubleIterator;
import it.unimi.dsi.fastutil.floats.FloatArrayList;
import it.unimi.dsi.fastutil.floats.FloatIterator;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntIterator;

import java.util.Iterator;

public class NumberIterator implements Iterable<Double> {

    private DoubleArrayList dList;
    private IntArrayList iList;
    private FloatArrayList fList;

    private final Object iterator;

    public NumberIterator(DoubleArrayList list) {
        this.dList = list;
        this.iterator = list.iterator();
    }

    public NumberIterator(FloatArrayList list) {
        this.fList = list;
        this.iterator = list.iterator();
    }

    public NumberIterator(IntArrayList list) {
        this.iList = list;
        this.iterator = list.iterator();
    }

    public double next() {
        if (dList != null) {
            return ((DoubleIterator) iterator).nextDouble();
        } else {
            return ((IntIterator) iterator).nextInt();
        }
    }

    public int nextInt() {
        if (dList != null) {
            return (int) ((DoubleIterator) iterator).nextDouble();
        } else {
            return ((IntIterator) iterator).nextInt();
        }
    }

    public float nextFloat() {
        if (fList != null) {
            return ((FloatIterator) iterator).nextFloat();
        }
        else if (dList != null) { // TODO (check for cast exception)
            return ((FloatIterator) iterator).nextFloat();
        } else {
            return ((IntIterator) iterator).nextInt();
        }
    }

    public boolean hasNext() {
        if (dList != null) {
            return ((DoubleIterator) iterator).hasNext();
        } else {
            return ((IntIterator) iterator).hasNext();
        }
    }

    public Iterator<Double> iterator() {
        if (dList != null) {
            return dList.iterator();
        } else {
            return new Iterator<Double>() {
                IntIterator intIterator = iList.iterator();
                @Override
                public boolean hasNext() {
                    return intIterator.hasNext();
                }

                @Override
                public Double next() {
                    return (double) intIterator.nextInt();
                }
            };
        }
    }
}

@@ -33,16 +33,75 @@
 mbers;%0A%0A
+import java.util.Iterator;%0Aimport java.util.ListIterator;%0A%0A
 import i
@@ -402,36 +402,8 @@
 r;%0A%0A
-import java.util.Iterator;%0A%0A
 publ
@@ -581,14 +581,23 @@
 nal 
-Object
+ListIterator%3C?%3E
  ite
@@ -967,32 +967,186 @@
 rator();%0A    %7D%0A%0A
+    public int nextIndex() %7B%0A        return iterator.nextIndex();%0A    %7D%0A%0A    public int previousIndex() %7B%0A        return iterator.previousIndex();%0A    %7D%0A%0A
     public doubl
@@ -1253,32 +1253,50 @@
 %0A        %7D else 
+if (iList != null)
 %7B%0A            re
@@ -1328,32 +1328,108 @@
 tor).nextInt();%0A
+        %7D else %7B%0A            return ((FloatIterator) iterator).nextFloat();%0A
         %7D%0A    %7D%0A
@@ -1559,32 +1559,50 @@
 %0A        %7D else 
+if (iList != null)
 %7B%0A            re
@@ -1634,32 +1634,114 @@
 tor).nextInt();%0A
+        %7D else %7B%0A            return (int) ((FloatIterator) iterator).nextFloat();%0A
         %7D%0A    %7D%0A
@@ -1784,17 +1784,17 @@
     if (
-f
+d
 List != 
@@ -1813,38 +1813,47 @@
         return (
-(F
+f
 loat
+) ((Double
 Iterator) iterat
@@ -1852,37 +1852,38 @@
 ) iterator).next
-Float
+Double
 ();%0A        %7D%0A  
@@ -1879,24 +1879,16 @@
        %7D
-%0A       
  else if
@@ -1885,25 +1885,25 @@
  %7D else if (
-d
+i
 List != null
@@ -1907,45 +1907,9 @@
 ull)
- %7B // TODO (check for cast exception)
+%7B
 %0A   
@@ -1918,36 +1918,34 @@
        return ((
-Floa
+In
 tIterator) itera
@@ -1945,36 +1945,34 @@
 ) iterator).next
-Floa
+In
 t();%0A        %7D e
@@ -1990,34 +1990,36 @@
        return ((
-In
+Floa
 tIterator) itera
@@ -2019,34 +2019,36 @@
 ) iterator).next
-In
+Floa
 t();%0A        %7D%0A 
@@ -2096,65 +2096,14 @@
     
-if (dList != null) %7B%0A            return ((DoubleIterator)
+return
  ite
@@ -2099,33 +2099,32 @@
  return iterator
-)
 .hasNext();%0A    
@@ -2123,90 +2123,8 @@
 ();%0A
-        %7D else %7B%0A            return ((IntIterator) iterator).hasNext();%0A        %7D%0A
     
@@ -2239,32 +2239,51 @@
 ;%0A        %7D else
+ if (iList != null)
  %7B%0A            r
@@ -2668,16 +2668,442 @@
      %7D;%0A
+        %7D else %7B%0A            return new Iterator%3CDouble%3E() %7B%0A                FloatIterator floatIterator = fList.iterator();%0A                @Override%0A                public boolean hasNext() %7B%0A                    return floatIterator.hasNext();%0A                %7D%0A%0A                @Override%0A                public Double next() %7B%0A                    return (double) floatIterator.nextFloat();%0A                %7D%0A            %7D;%0A
         

Fix NumberIterator (#347)