package rabbitescape.engine.util;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
public class LookupTable2D <T extends LookupItem2D> implements Iterable<T>
{
private final class ItemIterator implements Iterator<T>
{
private int cursor;
public ItemIterator()
{
this.cursor = 0;
}
@Override
public boolean hasNext()
{
return cursor < list.size();
}
@Override
public T next()
{
if( this.hasNext() )
{
return list.get( cursor++ );
}
throw new NoSuchElementException();
}
@Override
public void remove()
{
throw new UnsupportedOperationException();
}
}
@Override
public Iterator<T> iterator()
{
return new ItemIterator();
}
// Arrays of generics not allowed, use ArrayList instead
private final ArrayList<ArrayList<LookupItems2D<T>>> table;
private final List<T> list;
/**
* The size this table was created with. Note that changing the dimensions
* will not change the size of an existing table.
*/
public final Dimension size;
public LookupTable2D( List<T> list, Dimension size )
{
// The table can store items +/-1 outside the nominal size.
table = new ArrayList<ArrayList<LookupItems2D<T>>>( size.width + 2 );
for ( int x = -1; x < size.width + 1 ; x++ )
{
table.add( new ArrayList<LookupItems2D<T>>( size.height + 2 ) );
for ( int y = -1 ; y < size.height + 1 ; y++ )
{
table.get( i( x ) ).add( new LookupItems2D<T>( new Position( x, y ) ) );
}
}
for ( T item: list)
{
Position position = item.getPosition();
table.get( i( position.x ) ).get( i( position.y ) ).add( item );
}
this.list = list;
this.size = size;
}
/**
* Create an empty lookup table.
*
* @param size The dimensions of the table.
*/
public LookupTable2D( Dimension size )
{
this( new ArrayList<T>(), size );
}
/**
* @return The oldest item at this position.
*/
public T getItemAt( int x, int y )
{
return table.get( i( x ) ).get( i( y ) ).getItem( 0 );
}
public List<T> getItemsAt( int x, int y )
{
ArrayList<T> ret = new ArrayList<T>( table.get( i( x ) ).get( i( y ) ).getItems() );
return ret;
}
public void addAll( List<? extends T> newItems )
{
list.addAll( newItems );
for ( T item: newItems)
{
Position position = item.getPosition();
table.get( i( position.x ) ).get( i( position.y ) ).add( item );
}
}
public void add( T newItem )
{
list.add( newItem );
Position position = newItem.getPosition();
table.get( i( position.x ) ).get( i( position.y ) ).add( newItem );
}
public void removeAll( List<? extends T> itemsGoing )
{
list.removeAll( itemsGoing );
for ( T item: itemsGoing )
{
Position position = item.getPosition();
table.get( i ( position.x ) ).get( i( position.y ) ).remove( item );
}
}
public void removeItemsAt( int x, int y )
{
removeAll( getItemsAt( x, y ) );
}
public List<T> getListCopy()
{
return new ArrayList<T>( list );
}
/**
* Convert coordinate to index. This allows the table to
* store items 1 place outside the nominal size.
*/
private int i( int c )
{
return c + 1;
}
public Iterable<T> getItems()
{
return list;
}
/**
* @return The number of items in the lookup table.
*/
public int size()
{
return list.size();
}
public void debugPrint()
{
PrintStream p = System.out;
p.printf( "\n\n" );
for ( T o: this )
{
Position pos = o.getPosition();
p.printf( "List:(%02d,%02d)%s\n", pos.x, pos.y , o.toString() );
}
for ( int y = -1 ; y <= size.height ; y++ )
{
for ( int x = -1 ; x <= size.width ; x++ )
{
p.print( "" + getItemsAt( x, y ).size() );
}
p.println();
}
}
}