package fr.liglab.lcm.internals.nomaps;

import java.util.Iterator;

import fr.liglab.lcm.internals.TransactionReader;

/**
 * Decorates a transactions iterator : transactions are filtered (and, maybe, rebased) 
 * as they're read.
 */
class TransactionsFilteringDecorator implements Iterator<TransactionReader> {

	protected final Iterator<TransactionReader> wrapped;
	protected final int[] itemSupport;
	protected final int[] rebasing;
	protected FilteredTransaction instance;

	/**
	 * @param filtered
	 * @param itemSupport - only items having a positive value will be kept from "filtered"
	 * @param rebasing may be null, in which case no rebasing happens
	 */
	public TransactionsFilteringDecorator(Iterator<TransactionReader> filtered, int[] itemSupport, int[] rebasing) {
		this.wrapped = filtered;
		this.itemSupport = itemSupport;
		this.instance = null;
		this.rebasing = rebasing;
	}

	@Override
	public final boolean hasNext() {
		return this.wrapped.hasNext();
	}

	@Override
	public TransactionReader next() {
		if (this.instance == null) {
			this.instance = new FilteredTransaction(this.wrapped.next());
		} else {
			this.instance.reset(this.wrapped.next());
		}

		return this.instance;
	}

	@Override
	public final void remove() {
		this.wrapped.remove();
	}

	protected class FilteredTransaction implements TransactionReader {

		protected TransactionReader wrapped;
		protected int next;
		protected boolean hasNext;

		public FilteredTransaction(TransactionReader filtered) {
			this.reset(filtered);
		}

		public void reset(TransactionReader filtered) {
			this.wrapped = filtered;
			this.next = 0;

			this.findNext();
		}

		protected void findNext() {
			while (this.wrapped.hasNext()) {
				this.next = this.wrapped.next();
				if (itemSupport[this.next] > 0) {
					this.hasNext = true;
					return;
				}
			}

			this.hasNext = false;
		}

		@Override
		public final int getTransactionSupport() {
			return this.wrapped.getTransactionSupport();
		}

		@Override
		public final int next() {
			final int value = this.next;
			this.findNext();
			if (rebasing != null) {
				return rebasing[value];
			} else {
				return value;
			}
		}

		@Override
		public final boolean hasNext() {
			return this.hasNext;
		}
	}
}

@@ -1706,24 +1706,53 @@
 asNext()) %7B%0A
+%09%09%09%09if (rebasing == null) %7B%0A%09
 %09%09%09%09this.nex
@@ -1780,20 +1780,106 @@
 ();%0A%09%09%09%09
-if (
+%7D else %7B%0A%09%09%09%09%09this.next = rebasing%5Bthis.wrapped.next()%5D;%0A%09%09%09%09%7D%0A%09%09%09%09if (this.next != -1 && 
 itemSupp
@@ -2187,76 +2187,8 @@
 ();%0A
-%09%09%09if (rebasing != null) %7B%0A%09%09%09%09return rebasing%5Bvalue%5D;%0A%09%09%09%7D else %7B%0A%09
 %09%09%09r
@@ -2200,21 +2200,16 @@
  value;%0A
-%09%09%09%7D%0A
 %09%09%7D%0A%0A%09%09@

fix & simplify TransactionsFilteringDecorator