package net.vulkanmod.render.chunk.util;

import java.util.Iterator;
import java.util.function.Consumer;
import org.jetbrains.annotations.NotNull;

public class ResettableQueue<T> implements Iterable<T> {
   T[] queue;
   int position;
   int limit;
   int capacity;

   public ResettableQueue() {
      this(1024);
   }

   public ResettableQueue(int initialCapacity) {
      this.position = 0;
      this.limit = 0;
      this.capacity = initialCapacity;
      this.queue = (T[])(new Object[this.capacity]);
   }

   public boolean hasNext() {
      return this.position < this.limit;
   }

   public T poll() {
      T t = (T)this.queue[this.position];
      ++this.position;
      return t;
   }

   public void add(T t) {
      this.queue[this.limit++] = t;
   }

   public void ensureCapacity(int n) {
      while(this.limit + n > this.capacity) {
         int newSize = Math.max(this.limit + n, this.capacity * 2);
         this.resize(newSize);
      }

   }

   private void resize(int capacity) {
      this.capacity = capacity;
      T[] oldQueue = this.queue;
      this.queue = (T[])(new Object[this.capacity]);
      System.arraycopy(oldQueue, 0, this.queue, 0, oldQueue.length);
   }

   public int size() {
      return this.limit;
   }

   public void rewind() {
      this.position = 0;
   }

   public T get(int i) {
      return (T)this.queue[i];
   }

   public void clear() {
      this.position = 0;
      this.limit = 0;
   }

   public Iterator<T> iterator(boolean reverseOrder) {
      return reverseOrder ? new Iterator<T>() {
         int pos;
         final int limit;

         {
            this.pos = ResettableQueue.this.limit - 1;
            this.limit = -1;
         }

         public boolean hasNext() {
            return this.pos > -1;
         }

         public T next() {
            return (T)ResettableQueue.this.queue[this.pos--];
         }
      } : new Iterator<T>() {
         int pos = 0;
         final int limit;

         {
            this.limit = ResettableQueue.this.limit;
         }

         public boolean hasNext() {
            return this.pos < this.limit;
         }

         public T next() {
            return (T)ResettableQueue.this.queue[this.pos++];
         }
      };
   }

   public @NotNull Iterator<T> iterator() {
      return this.iterator(false);
   }

   public void forEach(Consumer<? super T> action) {
      for(int i = 0; i < this.limit; ++i) {
         action.accept(this.queue[i]);
      }

   }
}
